18

以下でsetattrは、最初の呼び出しで成功しますが、2 番目の呼び出しで失敗します。

AttributeError: 'method' object has no attribute 'i'

これはなぜですか? また、クラスのインスタンスごとではなく、1 つのインスタンスにのみ存在するようにメソッドに属性を設定する方法はありますか?

class c:

    def m(self):

        print(type(c.m))
        setattr(c.m, 'i', 0)

        print(type(self.m))
        setattr(self.m, 'i', 0)

パイソン 3.2.2

4

2 に答える 2

33

簡単な答え: バインドされたメソッドにカスタム属性を追加する方法はありません。

長い答えが続きます。

Python には、関数オブジェクトメソッド オブジェクトがあります。クラスを定義すると、defステートメントはクラスの名前空間内に存在する関数オブジェクトを作成します。

>>> class c:
...     def m(self):
...         pass
...
>>> c.m
<function m at 0x025FAE88>

関数オブジェクトには、__dict__ユーザー定義の属性を保持できる特別な属性があります。

>>> c.m.i = 0
>>> c.m.__dict__
{'i': 0}

メソッド オブジェクトは別の獣です。__func__これらは、対応する関数オブジェクトへの参照 ( ) とそのホスト オブジェクトへの参照 ( ) を保持するだけの小さなオブジェクトです__self__

>>> c().m
<bound method c.m of <__main__.c object at 0x025206D0>>
>>> c().m.__self__
<__main__.c object at 0x02625070>
>>> c().m.__func__
<function m at 0x025FAE88>
>>> c().m.__func__ is c.m
True

メソッド オブジェクトは__getattr__、関数オブジェクトへの属性アクセスを転送する特別な機能を提供します。

>>> c().m.i
0

__dict__これは、プロパティにも当てはまります。

>>> c().m.__dict__['a'] = 42
>>> c.m.a
42
>>> c().m.__dict__ is c.m.__dict__
True

ただし、属性の設定はデフォルトのルールに従います。独自の を持たないため、__dict__任意の属性を設定する方法はありません。

これは、存在しないスロットを設定しようとすると、スロットを定義__slots__しないユーザー定義クラスに似ています(詳細については、ドキュメントを参照してください)。__dict__AttributeError__slots__

>>> class c:
...     __slots__ = ('a', 'b')
...
>>> x = c()
>>> x.a = 1
>>> x.b = 2
>>> x.c = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'c' object has no attribute 'c'
于 2011-10-25T15:26:53.883 に答える
2

Q: 「クラスのインスタンスごとではなく、1 つのインスタンスにのみ存在するように、メソッドに属性を設定する方法はありますか?」

A: はい:

class c:

    def m(self):

        print(type(c.m))
        setattr(c.m, 'i', 0)

        print(type(self))
        setattr(self, 'i', 0)

リンク先の投稿の関数の静的変数は、メソッドには役立ちません。関数に属性を設定して、次回関数が呼び出されたときにこの属性を使用できるようにするため、カウンターなどを作成できます。

ただし、メソッドにはオブジェクト インスタンス (自己) が関連付けられています。したがって、代わりにインスタンスに属性を設定するだけでよいため、メソッドに属性を設定する必要はありません。実際、それはまさにインスタンスの目的です。

リンク先の投稿は、静的変数を使用して関数を作成する方法を示しています。Python でそうするのは見当違いだと思います。代わりに、この回答を見てください:関数内の静的変数に相当する Python は何ですか?

これが、明確で理解しやすい方法で Python で行う方法です。クラスを使用して呼び出し可能にします。関数に属性を設定することは可能であり、おそらくそれが良い考えである場合もありますが、一般的には人々を混乱させるだけです.

于 2011-10-26T01:17:51.273 に答える