一般解决方案:
如果您希望它全面工作,那么您可以__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))
给我们:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8]
请注意,__getattr__()
只有在属性不存在时才会调用。所以,如果你设置bb.b
为另一个值,你会得到它:
bb = B([A(i) for i in range(10)])
bb.b = 5
print(list(bb.a))
print(bb.b)
给我们:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5
显示不需要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]
原答案:
最简单的方法是使用生成器表达式。
class B(list):
"""
Some customization of this class...
"""
@property
def a(self):
return (item.a for item in self)
这个生成器表达式等价于:
@property
def a(self):
for item in self:
yield item.a
我还使用内置property()
函数作为装饰器,使其B.a
充当属性而不是函数。
然后我们可以这样做:
bb = B([A(i) for i in range(10)])
print(list(bb.a))
并得到:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
如果您确实想要一个列表而不是迭代器,则可以使用列表推导([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)
但是,这意味着发电机在第一次使用后就会耗尽,所以我建议不要这样做。