12

メタクラスで宣言されたメソッドはどうなるのだろうと思っていました。メタクラスでメソッドを宣言すると、最終的にはクラスメソッドになると思いましたが、動作は異なります。例

>>> class A(object):
...     @classmethod
...     def foo(cls):
...         print "foo"
... 
>>> a=A()
>>> a.foo()
foo
>>> A.foo()
foo

ただし、メタクラスを定義してメソッドfooを指定しようとすると、インスタンスではなく、クラスでも同じように機能するようです。

>>> class Meta(type): 
...     def foo(self): 
...         print "foo"
... 
>>> class A(object):
...     __metaclass__=Meta
...     def __init__(self):
...         print "hello"
... 
>>> 
>>> a=A()
hello
>>> A.foo()
foo
>>> a.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'foo'

ここで何が起こっているのですか?

編集:質問をぶつける

4

4 に答える 4

16

あなたは良い点を上げます。

オブジェクト、クラス、メタクラス間の関係をよりよく理解するための良いリファレンスは次のとおりです。

また、記述子に関するこのリファレンスは、Pythonでのルックアップのメカニズムについて非常に啓発的であることがわかりました。

しかし、成功したときになぜa.foo失敗するのか理解できません。A.fooオブジェクトの属性を検索しても、Pythonがオブジェクトを検出しない場合、クラス内の属性を正確に検索しないようA.fooです。検索すると、が検出されるためです。

編集:

おー!わかったと思います。これは、継承がどのように機能するかによるものです。上記のリンクによって提供されるスキーマを検討すると、次のようになります。

代替テキスト

概略的には、次のように要約されます。

type -- object
  |       |
Meta --   A  -- a

に行くということは、特定のインスタンスのクラスに行くことを意味します。上がるということは、親に行くことを意味します。

これで、継承メカニズムにより、ルックアップメカニズムが上記のスキーマで右折します。行きa → A → objectます。継承ルールに従うためにそうしなければなりません!明確にするために、検索パスは次のとおりです。

 object
   ^
   |
   A  <-- a

そうすると、明らかに、属性fooは見つかりません。

ただし、で属性を検索するとfoo、検索パスが次のようになっているため、属性が見つかります。A

type
  ^
  |       
Meta <--   A 

継承がどのように機能するかを考えるとき、それはすべて理にかなっています。

于 2010-02-11T16:43:33.700 に答える
9

ルールは次のようになります。オブジェクトの属性を検索するとき、オブジェクトのクラスとその親クラスも考慮されます。ただし、オブジェクトのクラスのメタクラスは考慮されません。クラスの属性にアクセスすると、そのクラスのクラスはメタクラスである見なされます。オブジェクトからそのクラスへのフォールバックは、クラスでの「通常の」属性ルックアップをトリガーしません。たとえば、属性がインスタンスでアクセスされるかそのクラスでアクセスされるかにかかわらず、記述子は異なる方法で呼び出されます。

メソッドは呼び出し可能な属性です(そして、__get__「self」が自動的に渡されるようにするメソッドがあります)。これにより、メタクラスのメソッドは、クラスで呼び出すとクラスメソッドのようになりますが、インスタンスでは使用できません。

于 2010-02-11T06:43:02.170 に答える
0

私が理解しているのは、Metaはクラスであり、Aはそのインスタンスであるということです。したがって、A.foo()を呼び出すと、オブジェクトとそのクラスがチェックされます。したがって、A.fooを試すときは、最初にA自体が保持するメソッドを調べ、次にそのクラスMetaのメソッドを調べます。Aはメソッドfoo自体を保持していないため、Metaのメソッドを使用し、実際にMeta.foo(A)を実行します。

同様に、a.fooが試行されると、最初にaを調べます。aはメソッドfooを保持しないため、Aを調べます。ただし、fooはMetaで保持されるため、Aもメソッドfooを保持しません。aもAもfooを保持しないため、AttributeErrorが発生します。

私はこれを変数と関数で試し、Metaクラスに属性txt ='txt'を入れました。これもAからアクセスできましたが、Aからはアクセスできませんでした。ですから、私は自分の理解が正しいと思う傾向がありますが、私はただ推測しています。

于 2010-02-14T04:34:29.940 に答える
0

少なくとも私にとっては、受け入れられた回答のリンクはなくなっています。だから私はいくつかのサプリメントを作りたいです:

3.データモデル— object .__ getattribute__

私の意見では2つの重要なポイントを挙げてください。

  • object.__getattribute__インスタンスの属性アクセスを制御します。
  • type.__getattribute__制御クラスの属性アクセス。
于 2019-06-15T07:43:59.530 に答える