1

をオーバーライドする何らかのクラスを作成する必要がありました__getattribute__。基本的に私のクラスはコンテナであり、ユーザーが追加したすべてのプロパティをself._meta辞書に保存します。

class Container(object):
    def __init__(self, **kwargs):
        super(Container, self).__setattr__('_meta', OrderedDict())
        #self._meta = OrderedDict()
        super(Container, self).__setattr__('_hasattr', lambda key : key in self._meta)

        for attr, value in kwargs.iteritems():
            self._meta[attr] = value

    def __getattribute__(self, key):
        try:
            return super(Container, self).__getattribute__(key)
        except:
            if key in self._meta : return self._meta[key]
            else:
                raise AttributeError, key

    def __setattr__(self, key, value):
        self._meta[key] = value
#usage:
>>> a = Container()
>>> a
<__main__.Container object at 0x0000000002B2DA58>
>>> a.abc = 1 #set an attribute
>>> a._meta
OrderedDict([('abc', 1)]) #attribute is in ._meta dictionary

基本クラスを継承するいくつかのクラスがContainerあり、それらのメソッドのいくつかには @property デコレータがあります。

class Response(Container):
    @property
    def rawtext(self):
        if self._hasattr("value") and self.value is not None:
            _raw = self.__repr__()
            _raw += "|%s" %(self.value.encode("utf-8"))

            return _raw

問題は、.rawtextアクセスできないことです。(私は属性エラーを取得します。) のすべてのキーにアクセスでき、基本クラス._metaによって追加されたすべての属性にアクセスできますが、@property デコレータによるメソッドからプロパティにはアクセスできません。基本クラスでオーバーライドする方法に関係していると思います。プロパティをアクセス可能にするにはどうすればよいですか?__setattr__object__getattribute__Container@property

4

2 に答える 2

8

__getattr__おそらくここではなく、こちらをご覧になることを考えたほうがいいと思います__getattribute__。違いは次のとおり __getattribute__です。存在する場合は無条件に呼び出されます。Python が__getattr__他の手段で属性を見つけられない場合にのみ呼び出されます。

于 2013-02-04T15:27:47.647 に答える
2

私は完全に mgilson に同意します。コードと同等であるがプロパティでうまく機能するサンプルコードが必要な場合は、次を試すことができます。

class Container(object):
    def __init__(self, **kwargs):
        self._meta = OrderedDict()
        #self._hasattr = lambda key: key in self._meta  #???
        for attr, value in kwargs.iteritems():
            self._meta[attr] = value

    def __getattr__(self, key):
        try:
            return self._meta[key]
        except KeyError:
            raise AttributeError(key)

    def __setattr__(self, key, value):
        if key in ('_meta', '_hasattr'):
            super(Container, self).__setattr__(key, value)
        else:
            self._meta[key] = value

あなたの_hasattr属性がよくわかりません。属性として入れますが、実際にはアクセスできる関数selfです...メソッドではないでしょうか?実際には、組み込み関数を簡単に使用する必要があると思いますhasattr:

class Response(Container):
    @property
    def rawtext(self):
        if hasattr(self, 'value') and self.value is not None:
            _raw = self.__repr__()
            _raw += "|%s" %(self.value.encode("utf-8"))

            return _raw

hasattr(container, attr)返されることに注意してください。True_meta

私を困惑させるもう 1 つのことは、なぜ . を使用するのかということですOrderedDict。つまり、 を反復処理しkwargs、反復は通常の であるためランダムな順序dictになり、 に項目​​を追加しますOrderedDict。これ_metaで、値がランダムな順序で含まれています。特定の注文が必要かどうかわからない場合は、単純に使用して、後でdict交換してください。OrderedDict

ちなみに、キャッチする例外を指定せずにanを使用しないでください。try: ... except:あなたのコードでは、実際にはAttributeErrors だけをキャッチしたかったので、次のようにする必要がありました。

try:
    return super(Container, self).__getattribute__(key)
except AttributeError:
    #stuff
于 2013-02-04T15:35:05.097 に答える