2012-03-17 4 views
8

v'è una limitazione sulla sintassi di accesso agli attributi, in Python (almeno nella realizzazione CPython 2.7.2):Perché i nomi attribuiti non possono essere parole chiave Python?

>>> class C(object): pass 
>>> o = C() 
>>> o.x = 123 # Works 
>>> o.if = 123 
    o.if = 123 
    ^
SyntaxError: invalid syntax 

La mia domanda è duplice:

  1. C'è una ragione fondamentale perché usare i nomi degli attributi delle parole chiave Python (come in o.if = 123) è vietato?
  2. È/dove è documentata la restrizione di cui sopra sui nomi degli attributi?

avrebbe senso fare o.class = …, in uno dei miei programmi, e io sono un po 'deluso di non essere in grado di farlo (o.class_ avrebbe funzionato, ma non sembra così semplice).

PS: Il problema è ovviamente che if e class sono parole chiave Python. La domanda è perché utilizzando parole chiave come nomi di attributi sarebbe vietato (non vedo alcuna ambiguità nell'espressione o.class = 123) e se questo è documentato.

+3

Perché parser è più semplice quando le parole chiave sono sempre parole chiave e non contestuali. Quindi il codice non arriva nemmeno al punto in cui c'è l'accesso agli attributi, è semplicemente un errore di sintassi sul livello di analisi (perché "if" fa parte della grammatica e non appare mai in questo posto). È lo stesso nella maggior parte delle lingue e la grammatica della lingua è la documentazione per questo. –

+2

Inoltre, 'cls' viene in genere utilizzato per i nomi che contengono riferimenti a classi. –

+0

Anche se si dispone di un parser che è in grado di distinguere le parole chiave da variabili/nomi di funzioni, non è garantito che si possa mettere in ombra l'altro in un caso d'angolo. È molto più facile mantenere la sanità mentale se basta semplicemente vietare l'uso di alcune dozzine di nomi. –

risposta

7

Perché parser è più semplice quando le parole chiave sono sempre parole chiave, e non contestuale (ad es if è una parola chiave quando sulla livello di istruzione, ma solo un identificatore quando si trova all'interno di un'espressione: per if sarà doppio doppio a causa di X if C else Y e for viene utilizzato nelle espressioni di lista e nelle espressioni del generatore).

Quindi il codice non arriva nemmeno al punto in cui vi è l'accesso agli attributi, è semplicemente respinto dal parser, proprio come l'indentazione errata (che è il motivo per cui è un SyntaxError e non AttributeError o qualcosa del genere). Non fa differenza se si utilizza if come nome di attributo, nome di una variabile, nome di una funzione o nome di un tipo. Non può mai essere un identificatore, semplicemente perché il parser assegna sempre l'etichetta "keyword" e lo rende un token diverso rispetto agli identificatori.

È lo stesso nella maggior parte delle lingue e la grammatica della lingua (+ specifica lexer) è la documentazione per questo. Language spec mentions it explicitly. Inoltre non cambia in Python 3.

Inoltre, proprio perché è possibile utilizzare setattr o __dict__ per fare un attributo con un nome riservato, non significa che si dovrebbe . Non forzare te/utente API a utilizzare getattr anziché l'accesso agli attributi naturali. getattr deve essere riservato per quando è necessario l'accesso a un nome attributo variabile.

+1

Così è come l'insegnante ci dice nelle classi del compilatore. Questo è il modo in cui i compilatori sono costruiti in modo classico. I token sono suddivisi, classificati in categorie e quindi analizzati se hanno senso dal parser. Ogni simbolo speciale come + o: ha la sua (unitaria) categoria, così come ogni parola riservata ("se", "o", "classe", "def", ecc.). Ogni altra parola appartiene a una categoria speciale: gli identificatori. Poiché "se" non è un identificatore, non può nominare un attributo, semplice come quello. Non sto dicendo che sia impossibile costruire un compilatore/analizzatore di codice in qualche altro modo, solo che questo è il modo in cui le cose vengono fatte in questi giorni ... – lvella

+0

@Ivella: +1 per il commento molto pertinente. – EOL

+0

@CatPlusPlus: concordato, su 'getattr' e' __dict__'. Stavo solo citandoli perché mostrano che i nomi degli attributi possono essere parole chiave anche se il solito sintassi object.attribute lo vieta. – EOL

1

Perché if è una parola chiave. Hai problemi simili con o.while e o.for:

pax> python 
>>> class C(object): pass 
... 

>>> o = C() 

>>> o.not_a_keyword = 123 

>>> o.if = 123 
    File "<stdin>", line 1 
    o.if = 123 
    ^
SyntaxError: invalid syntax 

>>> o.while = 123 
    File "<stdin>", line 1 
    o.while = 123 
     ^
SyntaxError: invalid syntax 

>>> o.for = 123 
    File "<stdin>", line 1 
    o.for = 123 
     ^
SyntaxError: invalid syntax 

Altre parole chiave in Python possono essere ottenuti con:

>>> import keyword 
>>> keyword.kwlist 
['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 
'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 
'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 
'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 
'while', 'with', 'yield'] 

Si dovrebbe non generalmente usare una parola chiave come nome di variabile in Python.

Suggerirei di scegliere un nome più descrittivo, ad esempio iface se si tratta di un'interfaccia oppure infld per un campo di input e così via.

Come per la tua domanda modifica come perché le parole chiave non sono consentite, semplifica notevolmente il parser se gli elementi lessicali sono liberi dal contesto. Dovendo trattare il token lessicale if come parola chiave in alcuni punti e un identificatore in altri introdurrebbe una complessità che non è realmente necessaria se si scelgono gli identificatori in modo più oculato.

Ad esempio, C++ dichiarazione:

long int int = char[new - int]; 

potrebbe (con qualche difficoltà) essere valutata con un analizzatore complesso basato su cui si verificano tali elementi lessicali (e ciò che esiste su entrambi i lati di essi). Ma, (almeno in parte) nell'interesse della semplicità (e leggibilità), ciò non è fatto.

+1

Sì, davvero. Ho aggiornato il titolo della domanda in modo da rendere esplicito il fatto che la domanda è il motivo per cui le parole chiave sarebbero vietate come nomi di attributi. Infatti, in 'o.class = 123', è ovvio che' class' dovrebbe essere un nome di attributo; tuttavia, questo non è valido (C) Python; ci devono essere buoni motivi per cui questo non dovrebbe essere ovvio per l'interprete CPython: quali sono queste ragioni? – EOL

3

Non credo che if possa essere utilizzato come nome di variabile o attributo (esplicitamente), poiché si tratta di una parola chiave.

È possibile, tuttavia, utilizzare setattr e getattr per aggirare questo in un modo disordinato

>>> class C(object): pass 
... 
>>> o = C() 
>>> setattr(o, 'if', 123) 
>>> getattr(o, 'if') 
123 
+0

Sì, davvero. Questo sembra ancora più bello dell'accesso a 'o .__ dict__'. Tuttavia, la domanda riguarda le ragioni di questa restrizione e se la restrizione è documentata. – EOL

+0

Il motivo è perché non è possibile sovrascrivere le parole chiave. Questo non ha bisogno di essere documentato. – Blender

+0

Mi piace la risposta di @Cat Plus Plus nei commenti principali. È stata una decisione di progettazione semplificare il parser. L'idioma python è quello di fare 'if_', o 'exec_', ecc. – jdi