У меня есть класс, который содержит список примерно так:
class Zoo:
def __init__(self):
self._animals = []
Я заполняю список животных объектами животных, которые имеют различные свойства:
class Animal:
def __init__(self, speed, height, length):
self._speed = speed
self._height = height
self._length = length
Вы можете представить себе подклассыживотных, которые имеют другие свойства.Я хочу иметь возможность писать методы, которые выполняют те же вычисления, но с разными атрибутами Animal.Например, в среднем.Я мог бы написать следующее в Zoo:
def get_average(self, propertyname):
return sum(getattr(x, propertyname) for x in self.animals) / len(self.animals)
Этот поиск строк не только мешает моей способности красиво документировать, но использование getattr
кажется странным (и, возможно, я просто нервничаю, передавая строки?),Если это хорошая стандартная практика, это нормально.Создание методов get_average_speed()
, get_average_height()
и get_average_length()
, особенно когда я добавляю больше свойств, также кажется неразумным.
Я понимаю, что пытаюсь инкапсулировать однострочник в этом примере, ноЕсть ли лучший способ создать такие методы, основанные на свойствах объектов в списке зоопарка?Я немного посмотрел на фабричные функции, поэтому, когда я их лучше понимаю, я думаю, что смогу написать что-то вроде этого:
all_properties = ['speed', 'height', 'length']
for p in all_properties:
Zoo.make_average_function(p)
И тогда любой экземпляр Zoo будет иметь методы с именем get_average_speed()
,get_average_height()
и get_average_length()
, в идеале с хорошими струнами документов.Сделав еще один шаг вперед, я бы очень хотел, чтобы сами объекты Animal рассказывали моему зоопарку, какие свойства можно превратить в методы get_average()
.Переходя к самому концу, скажем, я подкласс Animal и хотел бы указать, что он создает новый метод усреднения: (ниже приведен псевдокод, я не знаю, могут ли декораторы использоваться таким образом)
class Tiger(Animal):
def __init__(self, tail_length):
self._tail_length = tail_length
@Zoo.make_average_function
@property
def tail_length(self):
return self._tail_length
Затем, после добавления тигра в зоопарк, мой метод добавления животных в объект зоопарка будет знать, как создать метод get_average_tail_length()
для этого экземпляра зоопарка.Вместо того, чтобы вести список того, какие средние методы мне нужно сделать, объекты типа Animal указывают, какие вещи можно усреднить.
Есть ли хороший способ получить такой метод генерации?Или, кроме getattr()
, существует другой подход, чтобы сказать: "выполнить некоторые вычисления / работать с определенным свойством каждого члена в этом списке"?