2009-12-22 22 views
28

So che questo codice è corretto:Qual è la relazione tra __getattr__ e 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')() 


e questo è sbagliato:

# will __getattr__ affect the getattr? 

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

print getattr(a) 

Anche questo è sbagliato:

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


Dove dovremmo usare queste funzioni (__getattr__ e getattr)?

+0

possibile duplicato di [Capire la differenza tra \ _ \ _ getattr \ _ \ _ e \ _ \ _ getattribute \ _ \ _] (http://stackoverflow.com/questions/4295678/understanding-the-difference-tra- getattr-and-getattribute) – Trilarion

+1

@Trilarion che non è un duplicato corretto per questa domanda –

risposta

47

risposta di Alex era buono, ma ti fornisce un codice di esempio da quando lei ha chiesto per esso :)

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" 

Quindi, in risposta breve è

si utilizza

__getattr__ a definire come gestire gli attributi che non sono stati trovati

e

getattr a ottenere il attributi

+3

Fai attenzione se usi '__getattr__' perché interrompe il modulo' copia' integrato nel modulo a meno che tu non implementi '__copy__' e' __deepcopy__' per la tua classe. Mi ci è voluto un po 'di tempo per rintracciare questo bug ... Su 2.7 in ogni caso –

33

getattr è una funzione incorporata che richiede (almeno) due argomenti: l'oggetto da cui si ottiene l'attributo e il nome della stringa dell'attributo.

Se il nome della stringa è una costante, dicono 'foo', getattr(obj, 'foo') è esattamente la stessa cosa comeobj.foo.

Quindi, il caso d'uso principale per la funzione incorporata getattr è quando non si ha il nome dell'attributo come costante, ma piuttosto come variabile. Un secondo caso d'uso importante è quando si passano tre argomenti, anziché solo due: in tal caso, se l'attributo è assente dall'oggetto, getattr restituisce il terzo argomento "predefinito", anziché sollevare un'eccezione.

__getattr__ è un metodo speciale, definito in una classe, che viene invocata quando viene richiesta qualche attributo di un'istanza di quella classe, e altri modi normali di fornire tale attributo (tramite l'istanza di __dict__, slot, proprietà, e così on) tutti falliti. È possibile definirlo, ad esempio, quando si desidera delegare ricerche di attributo altrimenti non definite ad altri oggetti.

Così il vostro secondo esempio è sbagliato perché la funzione interna getattr può mai essere chiamato con un singolo argomento.

Il terzo fallisce perché il dizionario si sta cercando di "ottenere un attributo" dal non ha l'attributo - ha articoli, che sono totalmente disgiunto da attributi, naturalmente.

+2

Mentre la risposta è eccellente, @ zjm1126 voleva un esempio di codice perché il suo inglese non è così buono. – Kimvais

14

__getattr__() è una funzione speciale metodo che è possibile definire. Quando una ricerca di membro fallisce, questa funzione verrà chiamata.

getattr() è una funzione che è possibile chiamare per tentare una ricerca di membro. Se la ricerca ha esito positivo, si ottiene il membro (forse un oggetto funzione metodo o forse un oggetto attributo dati). getattr() può anche restituire un valore predefinito nel caso in cui la ricerca non vada a buon fine.

Se si dichiara una funzione membro __getattr__(), è possibile farlo a volte, oppure è possibile farlo funzionare ogni volta.

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 ha anche __getattribute__() che è sempre invitato ogni ricerca. È molto pericoloso perché può rendere impossibile l'accesso ai membri normalmente.

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

Oops, ora è impossibile accedere a a.v!

+1

+1 per aver menzionato __getattribute__ che immagino fosse effettivamente la domanda. – kibitzer

+0

Bella e semplice spiegazione di __getattribute__ che mi è sempre sembrata poco chiara. –

Problemi correlati