1

そこで、リストを拡張するクラスを作成しようとしています。リストの特定の部分を参照するように特定の特別な属性をマップするという追加の機能を備えています。このPy3kドキュメントページを使用して、次のコードを作成しました。アイデアは(私がsequenceこのクラスのインスタンスを持っていると言う)sequence.seqは、とまったく同じようsequence[0]sequence.index動作する必要がありsequence[2]、などとまったく同じように動作する必要があるということです。

リストへのクラス変数マッピング属性にアクセスできないように見えることを除いて、それはうまく機能しているようです。

このSOの質問を見つけましたが、答えが間違っているか、メソッド内で何かが異なります。を使用することもできますself.__class__.__map__が、内部__getattribute__にクラス変数が必要なため、無限再帰ループになります。

>>> class Sequence(list):
...      __map__ = {'seq': 0,
...                 'size': 1,
...                 'index': 2,
...                 'fdbid': 3,
...                 'guide': 4,
...                 'factors': 5,
...                 'clas': 6,
...                 'sorttime': 7,
...                 'time': 8,
...                 'res': 9,
...                 'driver': 10 }
...      
...      def __setattr__(self, name, value): # "Black magic" meta programming to make certain attributes access the list
...           print('Setting atr', name, 'with val', value)
...           try:
...                self[__map__[name]] = value
...           except KeyError:
...                object.__setattr__(self, name, value)
...      
...      def __getattribute__(self, name):
...           print('Getting atr', name)
...           try:
...                return self[__map__[name]]
...           except KeyError:
...                return object.__getattribute__(self, name)
...      
...      def __init__(self, seq=0, size=0, index=0, fdbid=0, guide=None, factors=None, 
...           sorttime=None, time=None):
...                super().__init__([None for i in range(11)]) # Be sure the list has the necessary length
...                self.seq = seq
...                self.index = index
...                self.size = size
...                self.fdbid = fdbid
...                self.guide = ''
...                self.time = time
...                self.sorttime = sorttime
...                self.factors = factors
...                self.res = ''
...                self.driver = ''
... 
>>> a = Sequence()
Setting atr seq with val 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 31, in __init__
  File "<stdin>", line 17, in __setattr__
NameError: global name '__map__' is not defined
4

2 に答える 2

1

.属性には、。ではなくドット()を使用してアクセスします[]。Pythonでは参照を省略できないため、。selfを使用してクラス変数にアクセスする必要がありますself.__map__。したがって、その位置にある要素にアクセスする場合は、が必要self[self.__map__[name]]です。

独自の目的で二重アンダースコアを挟んだ名前を使用することはお勧めできません。2つの主要なアンダースコア(名前マングリングを行う)でさえ、通常、必要以上に多くなります。__map__属性がパブリックAPIの一部ではないことをユーザーに示したいだけの場合は、それを呼び出します_map

于 2012-07-27T02:31:05.953 に答える
1

Sequence完全に定義されるまでメソッドは呼び出されSequence.__map__ないので、問題なく参照できます。例えば:

def __setattr(self, name, value):
    print('Setting atr', name, 'with val', value)
    try:
        self[Sequence.__map__[name]] = value
    except KeyError:
        object.__setattr__(self, name, value)

余談ですが、同じ名前のインスタンス属性も存在しない限り、オブジェクトを介してクラス属性にアクセスできることを示します。

class Foo:
    i = 3
    def __init__(self, overwrite):
        if overwrite:
            self.i = 4

f = Foo(False)
id(f.i) == id(Foo.i)     # Should be True
f = Foo(True)
id(f.i) == id(Foo.i)     # Should be False
于 2012-07-27T02:33:34.240 に答える