Un attributo è una variabile che viene cercata su un altro oggetto utilizzando la sintassi del punto: obj.attribute
. Il modo in cui Python è progettato, la ricerca degli attributi può fare una varietà di cose e questa varietà a volte può portare a bug se non capisci cosa sta accadendo (questo è ciò che la documentazione che hai collegato per avvisare).
Il problema di base è che una ricerca di attributi può trovare un valore memorizzato nel dizionario di istanza dell'oggetto oppure può trovare qualcosa dalla classe dell'oggetto (o una classe base, se c'è un'eredità in corso). I metodi sono funzioni memorizzate nella classe, ma di solito li usi osservandoli su un'istanza (che "lega" il metodo, inserendo l'oggetto come prima arguemnt quando viene chiamato il metodo).
L'esatta sequenza di ciò che viene controllato quando è un po 'complicato (ho descritto l'intero processo in an answer to another question), ma al livello di base, gli attributi di istanza hanno la precedenza sull'attributo di classe.
Se un attributo di istanza e un attributo di classe con lo stesso nome esistono entrambi, in genere solo l'attributo di istanza sarà accessibile. Questo può essere molto confuso se non è intenzionale.
Si consideri il seguente codice:
class Foo(object):
def __init__(self, lst):
self.lst = lst
def sum(self):
self.sum = sum(self.lst)
return self.sum
f = Foo([1,2,3])
print(f.sum())
print(f.sum())
Al fondo di questo codice, facciamo due chiamate identici. Il primo funziona bene, ma il secondo solleverà un'eccezione.
Questo perché la prima volta che cerchiamo f.sum
troviamo un metodo nella classe Foo
. Possiamo chiamare il metodo senza problemi. Il problema deriva dal fatto che il metodo sum
assegna il risultato del suo calcolo (la somma degli elementi in self.lst
) a un attributo di istanza chiamato anche sum
. Nasconde il metodo sum
dalla vista.
Quando la seconda chiamata f.sum()
ricerca f.sum
, trova l'attributo di istanza, contenente il numero intero 6
, anziché il metodo previsto. Un numero intero non è chiamabile, quindi otteniamo un'eccezione.
La soluzione, ovviamente, non è quella di utilizzare lo stesso nome per il metodo e l'attributo. Il codice sopra è un esempio piuttosto banale. Gli errori causati da questo tipo di cose in codice più complesso possono essere molto più difficili da capire.
Se si scrive codice che aggiunge attributi a oggetti di cui non si conosce molto, è necessario fare attenzione a evitare nomi comuni. Se stai scrivendo una lezione di mixin, considera l'uso di due trattini bassi di sottolineatura nei nomi degli attributi per attivare il mangling del nome di Python, che è progettato proprio per questo tipo di situazione.
La tua spiegazione è piuttosto semplice. Quindi, mi sembra che la documentazione che ho collegato voglia dire "attributo dati" = "attributo istanza", "attributo metodo" = "attributo classe". Se sbaglio, correggimi. –
Sì, è vero. Penso che la documentazione potrebbe essere piuttosto vecchia e non del tutto aggiornata. Certamente, "attributo di istanza" e "attributo di classe" sono termini molto più comuni al giorno d'oggi. Vale anche la pena notare che la situazione reale è un po 'più complicata di quella che ho presentato qui. Alcuni tipi di attributi di classe (ad esempio oggetti 'proprietà') avranno la precedenza sugli attributi di istanza. È improbabile che tu finisca in quella situazione per sbaglio, comunque. – Blckknght