NameError: il nome 'self' non è definito


144

Perché tale struttura

class A:
    def __init__(self, a):
        self.a = a

    def p(self, b=self.a):
        print b

dà un errore NameError: name 'self' is not defined?

Risposte:


159

I valori degli argomenti predefiniti vengono valutati al momento della definizione della funzione, ma selfè un argomento disponibile solo al momento della chiamata della funzione. Pertanto gli argomenti nell'elenco degli argomenti non possono riferirsi l'un l'altro.

È un modello comune per impostare un argomento su predefinito Nonee aggiungere un test per quello nel codice:

def p(self, b=None):
    if b is None:
        b = self.a
    print b

4
Anche se penso che quanto sopra non sia molto carino (vengo dal rubino dove le cose funzionano bene), quanto sopra in realtà funziona come una soluzione alternativa. È ancora imbarazzante che Python abbia scelto di renderlo non disponibile in un elenco di parametri.
Shevy

2
@shevy: "sé" non ha un significato speciale in Python, è solo il nome scelto convenzionalmente per il primo argomento. Puoi anche sostituire "self" con "me" o "x".
Max

Non c'è modo migliore per farlo? Se abbiamo una funzione che accetta una dozzina di argomenti predefiniti che dovrebbero fare riferimento a sé, abbiamo davvero bisogno di una dozzina di istruzioni if? Questo è terribilmente imbarazzante.
Richard J. Barbalace,

16

Per i casi in cui desideri avere anche l'opzione di impostare 'b' su Nessuno:

def p(self, **kwargs):
    b = kwargs.get('b', self.a)
    print b

6

Se sei arrivato qui tramite google, assicurati di aver dato self come primo parametro di una funzione di classe. Soprattutto se si tenta di fare riferimento a valori per quell'oggetto all'interno della funzione.

def foo():
    print(self.bar)

> NameError: il nome 'self' non è definito

def foo(self):
    print(self.bar)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.