我有以下(显然是简化的)课程
class A(object)
def __init__(self, a):
self.a = a
self.b = 'b'
# Other class attributes are added
class B(list):
"""
Some customization of this class...
"""
pass
BB = B([A(i) for i in range(10)])
Run Code Online (Sandbox Code Playgroud)
我想要做
B.a
Run Code Online (Sandbox Code Playgroud)
并从中获取a每个包含项目的所有属性的列表B.我知道为了做到这一点,我需要覆盖__getattr__,但我不确定实现它的最佳方法.这需要是通用的,因为B不知道A可能需要访问的任何属性.
有人可以就这个想法的实施提出一些建议吗?
如果您希望全面工作,那么您可以__getattr__()按照您的想法覆盖:
class A(object):
def __init__(self, a):
self.a = a
self.b = a-1
class B(list):
"""
Some customization of this class...
"""
def __getattr__(self, name):
return (getattr(item, name) for item in self)
bb = B([A(i) for i in range(10)])
print(list(bb.a))
print(list(bb.b))
Run Code Online (Sandbox Code Playgroud)
给我们:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)
请注意,__getattr__()仅在属性尚不存在时才会调用.所以,如果你设置bb.b为另一个值,你会得到它:
bb = B([A(i) for i in range(10)])
bb.b = 5
print(list(bb.a))
print(bb.b)
Run Code Online (Sandbox Code Playgroud)
给我们:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5
Run Code Online (Sandbox Code Playgroud)
示例显示不需要B了解它的内容:
>>> import datetime
>>> b = B([datetime.date(2012, 1, 1), datetime.date(2012, 2, 2), datetime.date(2012, 3, 3)])
>>> list(b.month)
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
最简单的方法是使用生成器表达式.
class B(list):
"""
Some customization of this class...
"""
@property
def a(self):
return (item.a for item in self)
Run Code Online (Sandbox Code Playgroud)
这个生成器表达式相当于:
@property
def a(self):
for item in self:
yield item.a
Run Code Online (Sandbox Code Playgroud)
我还使用了property()内置的装饰,使B.a充当一个属性,而不是一个功能.
然后我们可以这样做:
bb = B([A(i) for i in range(10)])
print(list(bb.a))
Run Code Online (Sandbox Code Playgroud)
得到:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
如果你肯定想要一个列表而不是一个迭代器,你可以使用列表推导([item.a for item in self]),但通常迭代器更有用,并且可以很容易地变成一个列表(如上所示).
请注意,您还可以通过分配生成器表达式来更简单地执行此操作:
class B(list):
"""
Some customization of this class...
"""
def __init__(self, *args):
super(B, self).__init__(*args)
self.a = (item.a for item in self)
Run Code Online (Sandbox Code Playgroud)
但是,这意味着发电机在首次使用后会耗尽,所以我会反对它.
| 归档时间: |
|
| 查看次数: |
810 次 |
| 最近记录: |