一般的な解決策:
これを全面的に機能させたい場合は、__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)
ただし、これは、最初の使用後にジェネレーターが使い果たされることを意味するため、使用しないことをお勧めします.