Frage

Ich habe mich gefragt, was mit Methoden passiert, die auf einer Metaklasse erklärt wurden. Ich habe erwartet, dass, wenn Sie eine Methode auf einer Metaklas deklarieren, sie jedoch ein Klassenmethode sein wird, das Verhalten jedoch anders ist. Beispiel

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

Wenn ich jedoch versuche, eine Metaklas zu definieren und ihm eine Methode zu geben, scheint es für die Klasse gleich zu funktionieren, nicht für die Instanz.

>>> 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'

Was ist hier genau hier los?

bearbeiten: stolpern die Frage

War es hilfreich?

Lösung

Sie setzen einen guten Punkt an.

Hier ist ein gute ReferenzUm die Beziehungen zwischen Objekten, Klassen und Metaklasse besser zu verstehen:

Ich finde auch Diese Referenz zu Deskriptoren ziemlich aufschlussreich über den Mechanismus der Suche in Python.

Aber ich kann nicht sagen, dass ich verstehe warum a.foo fällt aus, wenn A.foo gelingt es. Es scheint, dass, wenn Sie ein Attribut eines Objekts nachschlagen und Python es dort nicht findet, es tut nicht genau Schauen Sie das Attribut in der Klasse nach, denn wenn dies der Fall wäre, würde es finden A.foo.

BEARBEITEN:

Oh! Ich denke ich habe es. Es liegt an der Funktionsweise der Erbschaft. Wenn Sie das von der bereitgestellte Schema berücksichtigen Oben Link, es sieht aus wie das:

alt text

Schematisch läuft es auf:

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

Gehen links bedeutet, zur Klasse einer bestimmten Instanz zu gehen. Gehen hoch bedeutet, zum zu gehen Elternteil.

Jetzt macht der Vererbungsmechanismus den Look-up-Mechanismus ein Rechtskurve im Schema oben. Es geht a → A → object. Es muss dies tun, um der Erbschaftsregel zu folgen! Um es klar zu machen, lautet der Suchpfad:

 object
   ^
   |
   A  <-- a

Dann klar das Attribut foo wird nicht gefunden.

Wenn Sie nach dem Attribut suchen foo in A, Wie auch immer, es ist gefunden, weil der Lookup -Pfad lautet:

type
  ^
  |       
Meta <--   A 

Es macht alles Sinn, wenn man denkt, wie die Erbschaft funktioniert.

Andere Tipps

Die Regel lautet wie folgt: Bei der Suche nach einem Attribut für ein Objekt werden auch die Klasse des Objekts und seine übergeordneten Klassen berücksichtigt. Die Metaklasse einer Objektklasse ist jedoch nicht betrachtet. Wenn Sie auf ein Attribut einer Klasse zugreifen, ist die Klasse der Klasse die Metaklasse, so dass es so ist ist betrachtet. Der Fallback vom Objekt in seine Klasse löst keine "normale" Attribut -Suche in der Klasse aus: Zum Beispiel werden Deskriptoren anders als auf ein Attribut auf einer Instanz oder seiner Klasse zugegriffen.

Methoden sind Attribute, die aufrufbar sind (und eine haben __get__ Methode, die „Selbst“ automatisch übergeben wird.) Dadurch sind die Methoden auf der Metaklasse wie Klassenmethoden, wenn Sie sie in der Klasse aufrufen, aber nicht auf der Instanz verfügbar sind.

Ich verstehe, dass Meta eine Klasse ist und A eine Instanz davon ist. Wenn Sie also A.Foo () anrufen, überprüft es das Objekt und seine Klasse. Wenn es also A.foo probiert, schaut es zuerst die Methoden, die sich selbst hält, und dann die Methoden seiner Klasse, Meta. Als Hält keine Methode foo selbst, verwendet es die von Meta und führt daher wirklich Meta.foo (a) aus.

In ähnlicher Weise wird es beim Versuch von A.foo zuerst a schauen. Als Hält keine Methode foo, wird es A. durchsehen, aber auch keine Methode foo, da Foo in Meta gehalten wird. Da es weder ein noch ein Foo hält, wird es einen AttributeError erhöhen.

Ich habe dies mit einer Variablen und einer Funktion versucht, die in das Klassen -Meta ein Attribut txt = 'txt' eingebaut wurde, und dies war auch durch a zugänglich, aber nicht durch a. Ich bin also geneigt zu denken, dass ich in meinem Verständnis Recht habe, aber ich rate nur.

Die Links in der akzeptierten Antwort sind zumindest für mich verschwunden. Also möchte ich eine Ergänzung machen:

3. Datenmodell - Objekt .__ GetAttribute__

und geben Sie meiner Meinung nach zwei wichtige Punkte:

  • object.__getattribute__ Attributzugriff der Steuerinstanz.
  • type.__getattribute__ Steuerzugriff der Attribut der Klasse.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top