Un blocco di classe è zucchero sintattico per la costruzione di un dizionario, che viene quindi passato al metaclasse (solitamente type
) per costruire l'oggetto classe.
class A:
i = 1
def f(self):
print(i)
è più o meno equivalente a:
def f(self):
print(i)
attributes = {'f': f, 'i': 1)
A = type('A', (object,) attributes)
Visto in questo modo, non v'è alcun margine esterno il nome i
a venire da. Tuttavia, ovviamente, esiste un ambito temporaneo per l'esecuzione delle istruzioni nel blocco di classe. Sarebbe possibile per quel blocco di classe a desugar a qualcosa di più simile:
def attributes():
i = 1
def f(self):
print(i)
return locals()
A = type('A', (object,), attributes())
In questo caso il riferimento esterno per i
avrebbe funzionato. Tuttavia, questo andrebbe "contro la grana" della filosofia del sistema a oggetti di Python.
Python ha oggetti, che contengono attributi. Non c'è davvero alcun concetto di "variabili" diverse dalle variabili locali nelle funzioni (che possono essere annidate per creare una catena di portata). Un nome nudo viene considerato come una variabile locale, quindi in ambiti esterni (che provengono da funzioni).Attributi vengono ricercati, utilizzando la sintassi nome puntato, su altri oggetti, e sempre specificare quale oggetto di guardarsi.
C'è un protocollo per risolvere i riferimenti degli attributi, che dice che quando attribute
non si trova sulla obj
, obj.attribute
può essere risolto cercando nella classe obj
(e le sue classi base, usando l'ordine di risoluzione dei metodi). Questo è in realtà come vengono trovati i metodi; quando nell'esempio è stato eseguito a.f()
, l'oggetto a
non contiene alcun attributo f
, quindi viene cercata la classe a
(che è A
) e viene trovata la definizione del metodo.
Avere gli attributi di classe automaticamente disponibili in un ambito esterno per tutti i metodi sarebbe strano, perché nessun altro attributo funziona in questo modo. Sarebbe inoltre i seguenti inconvenienti:
- funzioni definite all'esterno della classe e ad essa assegnati dopo sarebbe necessario utilizzare sintassi diversa per l'attributo di classe di funzioni definite come parte di una classe.
- Perché è più breve, avrebbe incoraggiato riferimento alla classe di attributi tra cui staticmethods e classmethods nomi come nudi:
thing
invece di usare Class.thing
o self.thing
. Questo li fa apparire come moduli globali quando non lo sono (le definizioni dei metodi sono in genere abbastanza brevi da poter vedere facilmente che non sono definite localmente).
- Si noti che la ricerca degli attributi su
self
consente loro di giocare meglio con le sottoclassi, in quanto consente alle sottoclassi di sovrascrivere l'attributo. Questo probabilmente non è un grosso problema per le "costanti di classe", ma è molto importante per i metodi statici e i metodi di classe.
Queste sono le ragioni principali che vedo, ma alla fine è solo una scelta dei designer di Python. È strano che non si abbia questa capacità implicita di fare riferimento a variabili di classe, ma trovo che l'accesso alla variabile di classe e di istanza implicita in linguaggi come C++ e Java sia strano. Persone diverse hanno opinioni diverse
Sì. Io vedo. Quindi cercano di imporre l'uso di 'self' per accedere alle variabili di classe. È possibile che consentire l'accesso alle variabili di classe dai metodi avrebbe altre ripercussioni? – ovgolovin
@ovgolovin: Bene, aspettiamo quali spiegazioni escano altre persone. Forse qualcuno trova un buon collegamento web. –
In realtà, questo è un po 'di congetture congetturate "- controlla la risposta di Ben per capire cosa sta succedendo in Python – jsbueno