1

私は次の(明らかに単純化された)クラスを持っています

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)])

私はやってみたいです

B.a

aに含まれるすべてのアイテムからすべての属性のリストを取得しBます。これを行うには、上書きする必要があることはわかっています__getattr__が、これを実装するための最良の方法がわかりません。アクセスする必要があるかもしれないB属性のどれも知らないので、これは一般的である必要があります。A

誰かがこのアイデアの実装についてアドバイスを提供できますか?

4

1 に答える 1

5

一般的な解決策:

これを全面的に機能させたい場合は、__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)

ただし、これは、最初の使用後にジェネレーターが使い果たされることを意味するため、使用しないことをお勧めします.

于 2012-04-27T13:45:33.733 に答える