Better method to check all objects' parameters with a single call

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


Better method to check all objects' parameters with a single call



I want to get all objects which age is less than 18. How can easily do that?
Should I had to pass all objects to get_nonage to get it?


class People:
def __init__(self, uid, age):
self.uid = uid
self.age = age

def get_nonage(self):
# print nonage here which age<18
# expected output: {1: 11, 3: 15}
pass

p1 = People(1, 11)
p2 = People(2, 20)
p3 = People(3, 15)



...



People.get_nonage()


People.get_nonage()





First, get_nonage should probably not be an instance method. Second, yes, you will have to pass it all of the People object if you want it to search all of the People objects. But that implies that you should be storing them in a list, instead of in a bunch of separate variables. Then you just pass the list.
– abarnert
13 mins ago


get_nonage





Can I just know the class is People, then use some method of People to directly get all data of its objects without know how many objects I have, possible?
– Miss Bang
11 mins ago







Your design seems flawed here. Firstly, People is really Person. This is an important distinction. Once you create a person, you'll put them into an array (list) called people. Then, reducing/filtration/mapping operations are simple, in your case you're filtering on age: [p for p in people if p.age < 18]
– ggorlen
8 mins ago




People


Person


people


[p for p in people if p.age < 18]





Once you create a person, you'll put them into an array called people, what this mean?
– Miss Bang
7 mins ago





Where I add the array people?
– Miss Bang
7 mins ago




3 Answers
3



In order to search all of the People objects, you have to have all of the People objects.


People


People



But that implies you shouldn't have them in a bunch of separate variables in the first place, but in some collection, like a list.



Then, get_nonage can take that list.


get_nonage



While we're at it, there's no reason for get_nonage to be a method. It's not something that a People instance does, it's something you do to a bunch of People instances.


get_nonage


People


People



So:


class People:
# ...

def get_nonage(people):
nonage = {person.uid: person.age for person in people if person.age<18}
print(nonage)

people = [
People(1, 11),
People(2, 20),
People(3, 35)
]

get_nonage(people)



In a comment, you ask:



Can I just know the class is People, then use some method of People to directly get all data of its objects



What method would that be? You haven't written one. A class normally doesn't know all of its instances.



Of course if you really want it to, you can make a class record its instances in a class attribute. (A normal instance, like age, has a separate value for each instance. A class attribute has a single value shared by all instances.)


age



For example:


class People:
all_people =

def __init__(self, uid, age):
self.uid = uid
self.age = age
self.all_people.append(self)



If you do that, then you can make get_nonage into a class method—that is, a method meant to be called on the class itself, rather than on an instance. A class method gets the class, cls, as its first parameter, instead of an instance, self, and it can only access class attributes, like the all_people we just created above.


get_nonage


cls


self


all_people


@classmethod
def get_nonage(cls):
nonage = {person.uid: person.age for person in cls.all_people if person.age<18}
print(nonage)



And now, you can call it, without having to pass it anything, because it already knows everything:


people = [
People(1, 11),
People(2, 20),
People(3, 35)
]

People.get_nonage()



However, this is usually not a great design. For example, what if you wanted to delete a person? Previously, you'd just remove them from the list (or, in your original version, reassign p3 to something else). But then People.all_people won't know you did that; that person will still be there, and still be counted, even though you no longer have any way to access them.


p3


People.all_people



Try next:


class People:
def __init__(self, uid, age):
self.uid = uid
self.age = age

@classmethod
def get_nonage(cls, context):
print({obj.uid: obj.age for (obj_name, obj) in context.items() if type(obj) == cls and obj.age < 18})

p1 = People(1, 11)
p2 = People(2, 20)
p3 = People(3, 15)
People.get_nonage(globals())



Output:


{1: 11, 3: 15}



You can use global variable


non_age = {}


class People:
def __init__(self, uid, age):
self.uid = uid
self.age = age

if age < 18:
global non_age
non_age[uid] = age


if __name__ == '__main__':
p1 = People(1, 11)
p2 = People(2, 20)
p3 = People(3, 15)
print(non_age)






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Makefile test if variable is not empty

Will Oldham

'Series' object is not callable Error / Statsmodels illegal variable name