Лучший способ проверить параметры всех объектов одним вызовом

1

Я хочу получить все объекты, возраст которых меньше 18. Как это легко сделать? Должен ли я передать все объекты get_nonage, чтобы получить его?

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()

  • 1
    Во-первых, get_nonage вероятно, не должен быть методом экземпляра. Во-вторых, да, вам нужно будет передать все объекты People, если вы хотите, чтобы он выполнял поиск по всем объектам People. Но это подразумевает, что вы должны хранить их в списке, а не в куче отдельных переменных. Тогда вы просто передаете список.
  • 0
    Могу ли я просто знать, что класс People, и затем использовать какой-то метод People, чтобы напрямую получать все данные своих объектов, не зная, сколько объектов у меня есть, возможно?
Показать ещё 5 комментариев
Теги:

4 ответа

1
Лучший ответ

Чтобы искать все объекты People, вы должны иметь все объекты People.

Но это означает, что вы не должны иметь их в кучу отдельных переменных, в первую очередь, но в какой-то коллекции, например, в списке.

Затем get_nonage может взять этот список.

Пока мы находимся в этом, нет никаких причин для get_nonage. Это не то, что делает экземпляр People, это то, что вы делаете с кучей экземпляров People.

Так:

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)

В комментарии вы спрашиваете:

Могу ли я просто знать, что класс - это люди, а затем использовать какой-то метод людей, чтобы напрямую получать все данные его объектов

Какой метод это будет? Вы его не написали. Класс обычно не знает всех своих экземпляров.

Конечно, если вы действительно этого хотите, вы можете сделать запись класса его экземплярами в атрибуте класса. (Обычный экземпляр, например age, имеет отдельное значение для каждого экземпляра. Атрибут класса имеет одно значение, разделяемое всеми экземплярами.)

Например:

class People:
    all_people = []

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

Если вы это сделаете, вы можете сделать get_nonage в методе класса, то есть метод, предназначенный для 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)

И теперь вы можете это назвать, не передавая ничего, потому что он уже все знает:

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

People.get_nonage()

Тем не менее, это, как правило, не отличный дизайн. Например, что, если вы хотите удалить человека? Раньше вы просто удаляли их из списка (или в исходной версии переназначали p3 на что-то еще). Но тогда People.all_people не узнает, что вы это сделали; этот человек все еще будет там и все еще будет посчитан, даже если у вас больше нет доступа к ним.

2

Здесь ваш дизайн кажется ошибочным. Во-первых, People - это действительно Person. Это важное различие, поскольку имя класса должно соответствовать данным и функциям, из которых оно построено. В вашем случае группы людей не имеют ни одного возраста и идентификатора, но человек делает это. Когда вы создадите человека, вы поместите его в список, называемый людьми. Затем операции сокращения/фильтрации/отображения, такие как запрос, прост.

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

    def __repr__(self):
        return "Person (id: {}, age: {})".format(self.uid, self.age) 

people = [
    Person(1, 11),
    Person(2, 20),
    Person(3, 15)
]

underage_people = [p for p in people if p.age < 18]
print(underage_people)

Выход:

[Person (id: 1, age: 11), Person (id: 3, age: 15)]

Если вы хотите, вы можете поместить это понимание списка в статическую функцию класса, как в online-ответе, но мне это не кажется подходящим. Такой метод должен принадлежать другому классу, который управляет людьми, например, VoterRegistration приложений VoterRegistration который должен определить, кто не имеет права голоса. Или это может быть в People класса, который собирает Person в некотором роде; в любом случае, я думаю, что важно четко определить, какие данные и отношения вы моделируете с помощью классов и объектов здесь. В обоих случаях класс People будет иметь список членов объектов Person и множество функций для манипулирования и отчета по этим данным, например, get_underage() (как указано выше в списке comp) или get_median_age(). Вот конкретный эскиз того, о чем я говорю:

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

    def __lt__(self, other):
        return self.age < other.age

    def __repr__(self):
        return "Person (id: {}, age: {})".format(self.uid, self.age) 

class People:
    def __init__(self, people):
        self.people = people

    def get_underage(self):
        return [p for p in self.people if p.age < 18]

    def get_average_age(self):
        return sum([p.age for p in self.people]) / len(self.people)

    def get_oldest(self):
        return max(self.people)

    def get_youngest(self):
        return min(self.people)

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

print("Underage people: {}".format(people.get_underage()))
print("Average age: {}".format(people.get_average_age()))
print("Oldest: {}".format(people.get_oldest()))
print("Youngest: {}".format(people.get_youngest()))

Выход:

Underage people: [Person (id: 1, age: 11), Person (id: 3, age: 15)]
Average age: 15.333333333333334
Oldest: Person (id: 2, age: 20)
Youngest: Person (id: 1, age: 11)

и сменить игру.

-1

Попробуйте следующее:

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())

Выход:

{1: 11, 3: 15}
-1

Вы можете использовать глобальную переменную

non_age = {}


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

        if age < 18:
            non_age[uid] = age


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

Но я предлагаю вам не использовать глобальную переменную, попробуйте это

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


class NonAge:

    def __init__(self):
        self.non_age = {}

    def add_if_non_age(self, people):
        if people.age < 18:
            self.non_age[people.uid] = people.age

    def get_non_age(self):
        return self.non_age


if __name__ == '__main__':
    non_age = NonAge()
    p1 = People(1, 11)
    non_age.add_if_non_age(p1)

    p2 = People(2, 20)
    non_age.add_if_non_age(p2)

    p3 = People(3, 15)
    non_age.add_if_non_age(p3)

    print(non_age.get_non_age())

Ещё вопросы

Сообщество Overcoder
Наверх
Меню