2009-12-22 8 views
28

Ich weiß, dass dieser Code richtig ist:Was ist die Beziehung zwischen __getattr__ und getattr?

class A: 
    def __init__(self): 
     self.a = 'a' 
    def method(self): 
     print "method print" 

a = A() 
print getattr(a, 'a', 'default') 
print getattr(a, 'b', 'default') 
print getattr(a, 'method', 'default') 
getattr(a, 'method', 'default')() 


Und das ist falsch:

# will __getattr__ affect the getattr? 

class a(object): 
    def __getattr__(self,name): 
     return 'xxx' 

print getattr(a) 

Dies ist auch falsch:

a={'aa':'aaaa'} 
print getattr(a,'aa') 


Wo sollten wir diese Funktionen verwenden (__getattr__ und getattr)?

+0

mögliches Duplikat von [Verständnis des Unterschieds zwischen \ _ \ _ getattr \ _ \ _ und \ _ \ _ getattribute \ _ \ _] (http://stackoverflow.com/questions/4295678/understanding-the-difference-between- getattr-and-getattribute) – Trilarion

+1

@Trilarion das ist kein richtiges Duplikat für diese Frage –

Antwort

47

Alex Antwort war gut, aber man mit einem Beispielcode bereitstellt, da Sie danach gefragt :)

class foo: 
    def __init__(self): 
     self.a = "a" 
    def __getattr__(self, attribute): 
     return "You asked for %s, but I'm giving you default" % attribute 


>>> bar = foo() 
>>> bar.a 
'a' 
>>> bar.b 
"You asked for b, but I'm giving you default" 
>>> getattr(bar, "a") 
'a' 
>>> getattr(bar, "b") 
"You asked for b, but I'm giving you default" 

Also kurz gesagt Antwort ist

Sie verwenden

__getattr__ zu definieren wie man mit Attributen handelt, die nicht gefunden werden

und

getattr zu erhalten die

+3

Passen Sie auf, wenn Sie '__getattr__' verwenden, weil es das eingebaute' copy' Modul unterbricht, es sei denn, Sie implementieren auch '__copy__' und' __deepcopy__' für Ihre Klasse. Nahm mich etwas Zeit, um diesen Fehler zu verfolgen ... Auf 2.7 sowieso –

33

getattr ist eine integrierte Funktion, die (mindestens) zwei Argumente übernimmt: das Objekt, von dem Sie das Attribut erhalten, und den String-Namen des Attributs.

Wenn der String Name eine Konstante ist, sagen 'foo', getattr(obj, 'foo') ist genau das Gleiche wieobj.foo.

Der Hauptanwendungsfall für die integrierte Funktion getattr ist also, wenn Sie den Attributnamen nicht als Konstante haben, sondern als Variable. Ein zweiter wichtiger Anwendungsfall ist, wenn Sie drei Argumente übergeben und nicht nur zwei: Wenn das Attribut in dem Objekt nicht vorhanden ist, gibt getattr das dritte Argument "default" zurück, anstatt eine Ausnahme auszulösen.

__getattr__ ist eine spezielle Methode, die in einer Klasse definiert ist, die aufgerufen wird, wenn ein Attribut einer Instanz dieser Klasse angefordert wird, und andere normale Möglichkeiten zur Bereitstellung dieses Attributs (über die Instanz __dict__, Slots, Eigenschaften und so) on) alles gescheitert. Sie können es beispielsweise definieren, wenn Sie andernfalls nicht definierte Attributsuchvorgänge an andere Objekte delegieren möchten.

Also Ihr zweites Beispiel ist falsch, weil die eingebaute getattrnie mit einem einzigen Argument aufgerufen werden kann.

Die dritte schlägt fehl, weil das Wörterbuch, das Sie versuchen, "ein Attribut zu erhalten", dieses Attribut nicht hat - es hat Elemente, die von Attributen natürlich völlig getrennt sind.

+2

Während Ihre Antwort ausgezeichnet ist, wollte @ zjm1126 ein Codebeispiel, weil sein Englisch nicht so gut ist. – Kimvais

14

__getattr__() ist eine spezielle Methode Funktionsattribute, die Sie definieren können. Wenn eine Mitgliedersuche fehlschlägt, wird diese Funktion aufgerufen.

getattr() ist eine Funktion, die Sie aufrufen können, um eine Mitgliedersuche zu versuchen. Wenn die Suche erfolgreich ist, erhalten Sie das Mitglied (möglicherweise ein Methodenfunktionsobjekt oder möglicherweise ein Datenattributobjekt). getattr() kann auch einen Standardwert für den Fall, dass die Suche fehlschlägt, zurückgeben.

Wenn Sie eine __getattr__() Member-Funktion deklarieren, können Sie es manchmal erfolgreich machen, oder Sie können es jedes Mal erfolgreich machen.

class A(object): 
    def __getattr__(self, name): 
     return "I pretend I have an attribute called '%s'" % name 

a = A() 

print a.foo # prints "I pretend I have an attribute called 'foo'" 

Python hat auch __getattribute__() die immer auf jeder Lookup genannt wird. Es ist sehr gefährlich, weil es den Zugriff auf Mitglieder normalerweise unmöglich machen kann.

class A(object): 
    def __init__(self, value): 
     self.v = value 
    def __getattribute__(self, name): 
     return "I pretend I have an attribute called '%s'" % name 

a = A(42) 

print a.v # prints "I pretend I have an attribute called 'v'" 
print a.__dict__["v"] # prints "I pretend I have an attribute called '__dict__'" 

Hoppla, es ist jetzt unmöglich auf a.v zuzugreifen!

+1

+1 für die Erwähnung von __getattribute__ was ich denke, die Frage war eigentlich über. – kibitzer

+0

Schöne und einfache Erklärung von __getattribute__, die mir immer unklar schien. –

Verwandte Themen