2012-10-18 4 views
21

Wie unterscheidet Python Klasseneigenschaft, Instanzattribut und Methode, wenn die Namen identisch sind?python: Was passiert, wenn Klassenattribut, Instanzattribut und Methode alle den gleichen Namen haben?

class Exam(object): 

    test = "class var" 

    def __init__(self, n): 
     self.test = n 

    def test(self): 
     print "method : ",self.test 

test_o = Exam("Fine") 

print dir(test_o) 

print Exam.test 
print test_o.test 
test_o.test() 

Ausgang:

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'test'] 
<unbound method load.test> 
Fine 
Traceback (most recent call last): 
    File "example.py", line 32, in <module> 
    test_o.test() 
TypeError: 'str' object is not callable 

Wie

nennen
  1. Klassenattribut, Exam.test -><unbound method load.test> Ausgabe zeigt Methode
  2. Instanz Attribut test_o.test ->"Fine"
  3. Methode test_o.test() ->TypeError: 'str' object is not callable

Antwort

2

Sie

Exam.test(test_o) 

oder

Exam.test.__get__(test_o)() 

Im letzteren Fall schreiben können Sie die Tatsache verwenden, dass Methoden sind descriptors die <unbound method load.test> zu einem gebundenen konvertieren Methode, so dass Sie es mit einzelnen Klammern aufrufen können. Wenn Sie test_o.test() schreiben, weiß Python nicht, dass Sie versuchen, eine Methode aufzurufen. Sie versuchen möglicherweise, eine Funktion oder ein Callable Object aufzurufen, die auf dem Objekt als Instanzdatenmember installiert wurden. Stattdessen sucht es zuerst das Attribut test auf dem Objekt und dann auf seiner Klasse, aber da das Attribut für das Objekt vorhanden ist, verbirgt es die Methode für die Klasse.

Die Klasse Mitglied

test = "class var" 

nicht zugänglich ist (in der Tat existiert es nicht überall), weil es test nach der Methode überschrieben wird; Wenn ein class statement ausgeführt wird, wird sein Namespace in einem Dict gesammelt, bevor er an seine Metaklasse übergeben wird, und spätere Namen überschreiben frühere.

+0

was mit Aufruf test_o.test falsch ist()? – naren

+0

@naren Sie versuchen, das Instanzmitglied aufzurufen; siehe oben. – ecatmur

1

Sie können Methode als Klassenmethode aufrufen und übergeben Sie Ihre Instanz hinein:

Exam.test(test_o) 

Oder, wenn Sie nicht wollen, verwenden Exam:

type(test_o).test(test_o) 
17

Klasse Attribute sind durch die Klasse :

YourClass.clsattribute 

oder durch die Instanz (falls die Instanz nicht übergelaufen ist) Ritten die Klasse Attribut):

instance.clsattribute 

Methoden, wie by ecatmur in his answer angegeben, sind Deskriptoren und werden als Klassenattribute gesetzt.

Wenn Sie über die Instanz auf eine Methode zugreifen, wird die Instanz als Parameter self an den Deskriptor übergeben. Wenn Sie eine Methode von der Klasse aufrufen möchten, müssen Sie eine Instanz explizit als erstes Argument übergeben. So sind diese äquivalent:

instance.method() 
MyClass.method(instance) 

mit dem gleichen Namen für eine Instanz Attribut und ein Verfahren wird das Verfahren macht über die Instanz versteckt, aber die Methode ist noch über die Klasse zur Verfügung:

#python3 
>>> class C: 
...  def __init__(self): 
...   self.a = 1 
...  def a(self): 
...   print('hello') 
... 
>>> C.a 
<function a at 0x7f2c46ce3c88> 
>>> instance = C() 
>>> instance.a 
1 
>>> C.a(instance) 
hello 

Fazit : Geben Sie Instanzattributen und Methoden nicht den gleichen Namen. Ich vermeide das, indem ich aussagekräftige Namen gebe. Methoden sind Aktionen, deshalb verwende ich normalerweise Verben oder Sätze für sie. Attribute sind Daten, daher verwende ich Substantive/Adjektive für sie, und dies vermeidet die Verwendung der gleichen Namen für beide Methoden und Attribute.

Beachten Sie, dass Sie einfach kein Klassenattribut mit demselben Namen wie eine Methode haben können, da die Methode es vollständig überschreiben würde (am Ende sind Methoden nur Klassenattribute, die aufrufbar sind und automatisch eine Instanz der Klasse erhalten) als erstes Attribut).

0

Wie
Klasse Attribut nennen, Exam.test

Sie können nicht, weil, wenn def test(self) der Name Ausführung test wird in der Klasse der Methode gebunden und der Verweis auf "class var" verloren.

Instanz Attribut test_o.test -> "Fine"

Sie haben es schon getan.

Methode test_o.test()

Sie können es nicht so nennen, weil, wenn self.test = n der Name Ausführung test auf jedes Objekt gebunden ist n Referenzen in der Instanz und den Verweis auf das Verfahren in dem Fall verloren .

Aber wie in anderen Antworten darauf können Sie die Methode in der Klasse aufrufen und die Instanz es passieren: Exam.test(test_o)

Verwandte Themen