2014-08-29 15 views
16

ho questa classe:Python - classe accesso variabili da esempio

class ReallyLongClassName: 

    static_var = 5 

    def instance_method(self): 
     ReallyLongClassName.static_var += 1 

C'è qualche modo per accedere alla variabile statica utilizzando la variabile di sé? Preferirei fare qualcosa come class(self).static_var += 1, perché i nomi lunghi sono illeggibili.

risposta

24

Utilizzare self.__class__.classAttr. Questo dovrebbe funzionare per entrambe le vecchie classi di stile &.

+0

Questa risposta dovrebbe essere svalutata più ... evita il rischio di digitare l'intero nome della classe, specialmente se è lungo solo per ottenere un attributo. – repzero

+0

È in qualche modo migliore di 'type (self)'? – Alexey

+0

@Alexey guarda i commenti su https://stackoverflow.com/a/25577642/5241481 –

23

la risposta è "sì, ma ..."

Il modo migliore per capire è quello di provare in realtà:

>>> class RLCN: 
...  static_var = 5 
...  def method1(self): 
...   RLCN.static_var += 1 
...  def method2(self): 
...   self.static_var += 1 
>>> rlcn = RLCN() 
>>> RLCN.static_var, rlcn.static_var 
(5, 5) 
>>> rlcn.static_var 
5 
>>> rlcn.method1() 
>>> RLCN.static_var, rlcn.static_var 
(6, 6) 
>>> rlcn.method2() 
>>> RLCN.static_var, rlcn.static_var 
(6, 7) 

Che cosa è successo?

Bene, accesso a un attributo di classe tramite self funziona correttamente. Se non esiste alcun attributo di istanza con lo stesso nome, si ottiene l'attributo class.

Ma assegnando a esso nasconde l'attributo di classe con un nuovo attributo di istanza con lo stesso nome. Che probabilmente non è quello che volevi.

Si noti che questo significa che è possibile utilizzare gli attributi di classe come "valori predefiniti" o "valori iniziali" per gli attributi di istanza. Ma non sono sicuro che sia molto pitonico farlo; cosa sta realmente accadendo e che novizio (in particolare qualcuno proveniente da, ad esempio, C++ 11 o Java) pensa che lo stia accadendo, sono molto diversi.

(Le cose diventano un po 'più complicato quando si tratta con i descrittori, come metodi o @property s, ma ignoriamo che,., Nel caso semplice che si sta discutendo, non è rilevante)


Preferisco fare qualcosa come class (self) .static_var + = 1, perché i nomi lunghi sono illeggibili.

È possibile, è sufficiente scriverlo correttamente: type è la funzione che restituisce il tipo di qualsiasi oggetto. Quindi:

type(self).static_var += 1 

Questo ha il vantaggio di essere dinamici (per esempio, quando si ha l'ereditarietà multipla e non si sa da che parte un @property viene da, probabilmente non si vuole elencare esplicitamente un nome di classe, fondamentalmente per lo stesso motivo si desidera utilizzare super() invece di chiamare esplicitamente un metodo di classe base).

Questo ha lo svantaggio di non lavorare su classi vecchio stile in Python 2.x, ma non dovresti comunque utilizzarli. Soprattutto nelle classi che hanno bisogno di attributi di classe, perché quelli sono esattamente i tipi con cui spesso si desidera aggiungere @classmethod s, @property s, ecc. E nessuno di questi funziona con le classi vecchio stile (insieme a molte altre cose). Se hai davvero bisogno di gestire classi vecchio stile e nuovo stile in modo trasparente per qualche motivo, self.__class__ funziona con classi vecchio stile. Non sono sicuro che sia garantito il funzionamento con classi di nuovo stile; i documenti dicono che il valore di ritorno di type(object) è "generalmente lo stesso oggetto restituito da object.__class__", ma non dice a quali condizioni "in generale" non è vero. È anche documentato come special attribute "added by the implementation" for "several object types" in 3.x. In pratica, non conosco casi in cui sono diversi in 3.xe in 2.x, il caso più importante in cui sono diversi sono le classi vecchio stile.

+0

Sembra che 'type (self) .static_var + = 1' funzioni solo in Python3. –

+0

@AntonSavin: No, funziona correttamente in Python 2. Guardalo [qui] (http://repl.it/XrJ) in Python 2.7.2. – abarnert

+0

Ah, e [come questo] (http://repl.it/XrJ/1) non è così. –

Problemi correlati