2016-07-26 16 views
2

Gemäß dem Python 2.7.12 Dokumentation Vermeidung ErstellenObjekts neue Methode

Wenn das Attribut ein Benutzer-definierte Methode Objekt ist, ist ein neues Methode Objekt nur dann, wenn die Klasse erstellt, aus dem es zu sein abgerufen ist das gleiche oder eine abgeleitete Klasse der Klasse, die im ursprünglichen Methodenobjekt gespeichert ist; andernfalls wird das ursprüngliche Methodenobjekt verwendet, wie es ist.

Ich versuche, diesen Absatz zu verstehen, durch das Schreiben von Code:

# Parent: The class stored in the original method object 
class Parent(object): 
    # func: The underlying function of original method object 
    def func(self): 
     pass 
    func2 = func 

# Child: A derived class of Parent 
class Child(Parent): 
    # Parent.func: The original method object 
    func = Parent.func 

# AnotherClass: Another different class, neither subclasses nor subclassed 
class AnotherClass(object): 
    # Parent.func: The original method object 
    func = Parent.func 

a = Parent.func 
b = Parent.func2 
c = Child.func 
d = AnotherClass.func 

print b is a 
print c is a 
print d is a 

Die Ausgabe lautet:

False 
False 
False 

Ich erwarte, dass es sein:

False 
False 
True 
+0

Versuchen Sie: 'Drucken Parent.func ist Parent.func'. –

+0

@ Robᵩ 'print Parent.func ist Parent.func' gibt' False', aber 'print a is a' ergibt' True'. –

Antwort

3

Jedes Mal, wenn Sie Parent.func schreiben, erhalten Sie ein neues ungebundenes Methodenobjekt So ändert sich AnotherClass.func nie, aber Parent.func tut. Sie können dies sehen, wenn Sie etwas tun:

a = Parent.func 
a2 = Parent.func 
b = Parent.func2 
c = Child.func 
d = AnotherClass.func 
d2 = AnotherClass.func 

Dann:

>>> a is a2 
False 
>>> d is d2 
True 

So Ihre Kommentare zu „der ursprünglichen Methode Objekt“ beziehen, sind etwas irreführend. Jeder Teil Ihres Codes, der Parent.func auswertet, erhält ein anderes Methodenobjekt. (Beachten Sie, dass das angegebene Zitat nicht für Parent.func gilt, da func wie in Parent geschrieben kein Methodenobjekt ist; es ist ein Funktionsobjekt. Nur wenn Sie auf das Attribut zugreifen, indem Sie Parent.func schreiben, erhalten Sie ein Methodenobjekt.)

Ich füge ein bisschen hier, um das Zitat zu klären, das Sie gaben.

Ich denke, Sie sind falsch, was dieses Zitat sagt. Dies liegt möglicherweise daran, dass das Zitat etwas vage bezüglich der Unterscheidung zwischen "dem Attribut" und dem Wert ist, der durch das Erhalten dieses Attributs erhalten wurde.

Lassen Sie mich klären, indem Sie zwei Begriffe trennen. In einem Ausdruck wie something.attr verwende ich "den Rohwert", um auf den tatsächlichen Wert zu verweisen, der in dem Klassen-/Objektverzeichnis gespeichert ist, d. H. Den Wert something.__dict__['attr']. Ich verwende "den ausgewerteten Wert", um auf das tatsächliche Ergebnis der Bewertung something.attr zu verweisen. Der Unterschied zwischen den beiden ist, dass die descriptor protocol auf dem Rohwert aktiviert ist, um den ausgewerteten Wert zu erhalten.

Die von Ihnen zitierte Dokumentation beschreibt eine Situation, in der der Wert raw ein Methodenobjekt ist. Dies ist in Ihren Definitionen von Child und AnotherClass der Fall. Das Zitat tut nicht gelten für func innerhalb Parent, denn in diesem Fall ist der Rohwert keine Methode; Es ist eine Funktion. In diesem Fall gilt der folgende Absatz der Dokumentation:

Wenn ein benutzerdefiniertes Methodenobjekt erstellt wird, indem ein benutzerdefiniertes Funktionsobjekt abgerufen wird ...

Mit anderen Worten, die Dokumentation, die Sie zitiert („Wenn das Attribut ist eine benutzerdefinierte Methode Objekt“) gilt für Fälle wie folgt aus:

obj = [a method object] 

class Foo(object): 
    attr = obj 

Ihre zitierte Dokumentation gilt nicht für die folgenden Fall. In diesem Fall ist das Attribut "ein benutzerdefiniertes Funktionsobjekt":

func = [a function object] 

class Foo(object): 
    attr = func 

In Ihrem Beispiel gibt es kein "Originalmethodenobjekt". Sie können nur ein Methodenobjekt abrufen, nachdem die Klasse definiert ist. Das "Original" -Objekt ist ein Funktionsobjekt. Wenn Sie im Klassenhauptteil func schreiben, definieren Sie eine Funktion; Nur wenn Sie ZugriffParent.func erhalten, erhalten Sie ein Methodenobjekt.

+0

Aber warum gibt es jedes Mal ein neues Objekt zurück? –

+0

@Rawing: Sehen Sie ein wenig weiter unten in der gleichen Dokumentation, die Sie zitiert haben: "Beachten Sie, dass die Transformation vom Funktionsobjekt zum (ungebundenen oder gebundenen) Methodenobjekt jedes Mal stattfindet, wenn das Attribut von der Klasse oder Instanz abgerufen wird." Die Tatsache, dass das Objekt jedes Mal anders ist, ist im Wesentlichen eine Implementierungsdetail (und in Python 3 sind ungebundene Methodenobjekte nicht mehr vorhanden), aber es gibt sicherlich keine Garantie, dass das Methodenobjekt jemals dasselbe sein wird. – BrenBarn

+0

@Rawing: Method-Objekte sind kurzlebig und einfach aus einer freien Liste zuzuordnen. Sie herumzuhalten würde den Speicherverbrauch erhöhen und die Implementierung erschweren. – user2357112