Peb*_*bby 5 python attributes list object python-3.x
我有一个包含如下列表的类:
class Zoo:
def __init__(self):
self._animals = []
Run Code Online (Sandbox Code Playgroud)
我使用具有各种属性的动物对象填充动物列表:
class Animal:
def __init__(self, speed, height, length):
self._speed = speed
self._height = height
self._length = length
Run Code Online (Sandbox Code Playgroud)
您可以想象具有其他属性的Animal的子类.我希望能够编写执行相同计算但在Animal的不同属性上的方法.例如,平均值.我可以在Zoo中编写以下内容:
def get_average(self, propertyname):
return sum(getattr(x, propertyname) for x in self.animals) / len(self.animals)
Run Code Online (Sandbox Code Playgroud)
那个字符串查找不仅仅是因为我能够很好地记录,但是使用getattr
看起来很奇怪(也许我只是紧张地传递字符串?).如果这是一个很好的标准做法,那很好.创建get_average_speed()
,get_average_height()
和get_average_length()
方法,特别是当我添加更多属性时,似乎也是不明智的.
我意识到我试图在这个例子中封装一个单行程序,但是有没有更好的方法来根据Zoo列表中对象的属性创建这样的方法?我看了一下工厂的功能,所以当我更好地理解它们时,我想我可以这样写:
all_properties = ['speed', 'height', 'length']
for p in all_properties:
Zoo.make_average_function(p)
Run Code Online (Sandbox Code Playgroud)
然后动物园的任何实例都会有所谓的方法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
Run Code Online (Sandbox Code Playgroud)
然后,在向动物园添加Tiger时,我将动物添加到Zoo对象的get_average_tail_length()
方法将知道为Zoo的该实例创建方法.动物类型的对象不是必须保留我需要制作的平均方法的列表,而是指示可以平均的事物.
有没有一种很好的方法来生成这种方法?或者除了getattr()
说"对这个列表中每个成员的特定属性做一些计算/工作" 之外还有另一种方法吗?
尝试这个:
import functools
class Zoo:
def __init__(self):
self._animals = []
@classmethod
def make_average_function(cls, func):
setattr(cls, "get_average_{}".format(func.__name__), functools.partialmethod(cls.get_average, propertyname=func.__name__))
return func
def get_average(self, propertyname):
return sum(getattr(x, propertyname) for x in self._animals) / len(self._animals)
class Animal:
def __init__(self, speed, height, length):
self._speed = speed
self._height = height
self._length = length
class Tiger(Animal):
def __init__(self, tail_length):
self._tail_length = tail_length
@property
@Zoo.make_average_function
def tail_length(self):
return self._tail_length
my_zoo = Zoo()
my_zoo._animals.append(Tiger(10))
my_zoo._animals.append(Tiger(1))
my_zoo._animals.append(Tiger(13))
print(my_zoo.get_average_tail_length())
Run Code Online (Sandbox Code Playgroud)
注意:如果不同动物园有不同种类的动物,会导致混乱。
例子
class Bird(Animal):
def __init__(self, speed):
self._speed = speed
@property
@Zoo.make_average_function
def speed(self):
return self._speed
my_zoo2 = Zoo()
my_zoo2._animals.append(Bird(13))
print(my_zoo2.get_average_speed()) # ok
print(my_zoo.get_average_speed()) # wrong
print(my_zoo2.get_average_tail_length()) # wrong
Run Code Online (Sandbox Code Playgroud)