2012-03-17 12 views
8

hay una restricción sobre la sintaxis de acceso de atributo, en Python (al menos en la implementación CPython 2.7.2):¿Por qué los nombres de atributos no son palabras clave de Python?

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

Mi pregunta es doble:

  1. ¿Hay una razón fundamental ¿por qué está prohibido el uso de nombres de atributos de palabra clave Python (como en o.if = 123)?
  2. ¿Dónde/dónde se documenta la restricción anterior en los nombres de atributos?

Tendría sentido hacer o.class = …, en uno de mis programas, y estoy un poco decepcionado por no ser capaz de hacerlo (o.class_ funcionaría, pero no se ve tan simple).

PS: El problema es obviamente que if y class son palabras clave de Python. La pregunta es por qué usando palabras clave como nombres de atributos estaría prohibido (no veo ninguna ambigüedad en la expresión o.class = 123), y si esto es documentado.

+3

Porque el analizador es más simple cuando las palabras clave son siempre palabras clave y no contextuales. Entonces el código ni siquiera llega al punto donde hay acceso de atributos, es simplemente un error de sintaxis en el nivel de análisis sintáctico (porque 'si' es parte de la gramática y nunca aparece en este lugar). Es lo mismo en la mayoría de los idiomas, y la gramática del lenguaje es la documentación para eso. –

+2

Además, 'cls' se usa generalmente para nombres que contienen referencias a clases. –

+0

Incluso si tiene un analizador que puede distinguir las palabras clave de los nombres de variables/funciones, no es garantía de que uno pueda sombrear al otro en un caso de esquina. Es mucho más fácil mantener la cordura si simplemente prohíbe el uso de unas pocas docenas de nombres. –

Respuesta

7

Debido analizador es más sencillo cuando las palabras clave son siempre las palabras clave, y no contextual (por ejemplo if es una palabra clave cuando en el nivel de declaración, pero solo un identificador cuando está dentro de una expresión - para if sería doblemente difícil debido a X if C else Y, y for se usa en listas de comprensión y expresiones de generador).

Así que el código ni siquiera llega al punto donde hay acceso de atributo, simplemente es rechazado por el analizador, al igual que una sangría incorrecta (por eso es SyntaxError, y no AttributeError o algo así). No se diferencia si usa if como un nombre de atributo, un nombre de variable, un nombre de función o un nombre de tipo. Nunca puede ser un identificador, simplemente porque el analizador siempre le asigna una etiqueta de "palabra clave" y lo convierte en un token diferente de los identificadores.

Es lo mismo en la mayoría de los idiomas, y la gramática del lenguaje (especificación + lexer) es la documentación para eso. Language spec mentions it explicitly. También no cambia en Python 3.

Además, sólo porque se puede utilizar setattr o __dict__ para hacer un atributo con un nombre reservado, no se debe significa que sean. No fuerce usted/usuario API para usar getattr en lugar de acceso de atributo natural. getattr debe reservarse para cuando se necesita el acceso a un nombre de atributo variable.

+1

Así es como nos dicen los maestros en las clases de compilación. Así es como los compiladores se construyen de forma clásica. Los tokens se dividen, se clasifican en categorías y luego se analizan si tienen sentido para el analizador. Cada símbolo especial como + o: tiene su propia categoría (unitaria), así como también cada palabra reservada ("si", "o", "clase", "def", etc.). Cada otra palabra pertenece a una categoría especial: los identificadores. Como "si" no es un identificador, no puede nombrar un atributo, tan simple como eso. No digo que sea imposible construir un compilador/analizador de código de alguna otra manera, así es como se hacen las cosas estos días ... – lvella

+0

@Ivella: +1 para el comentario muy relevante. – EOL

+0

@CatPlusPlus: De acuerdo, sobre 'getattr' y' __dict__'. Solo mencioné esto porque muestran que los nombres de los atributos pueden ser palabras clave, aunque la sintaxis habitual de object.attribute lo prohíbe. – EOL

1

Porque if es una palabra clave. Usted tiene problemas similares con o.while y 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 

Otras palabras clave en Python se pueden obtener 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'] 

Usted debe no suelen utilizar una palabra clave como nombre de la variable en Python.

Sugeriría elegir un nombre más descriptivo, como iface si se trata de una interfaz, o infld para un campo de entrada y así sucesivamente.

En cuanto a su pregunta edite como por qué palabras clave no están permitidas, simplifica mucho los analizadores si los elementos léxicos están libres de contexto. Tener que tratar el token léxico if como una palabra clave en algunos lugares y un identificador en otros introduciría complejidad que no es realmente necesaria si elige sus identificadores de forma más inteligente.

Por ejemplo, el C++ declaración:

long int int = char[new - int]; 

podría (con un poco de dificultad) ser evaluados con un analizador complejo en base a donde se producen los elementos léxicos (y lo que existe a ambos lados de ellos). Pero, (al menos parcialmente) en aras de la simplicidad (y legibilidad), esto no se hace.

+1

Sí, de hecho. Actualicé el título de la pregunta para hacer explícito el hecho de que la pregunta es por qué las palabras clave estarían prohibidas como nombres de atributos. De hecho, en 'o.class = 123', es obvio que' class' debe ser un nombre de atributo; sin embargo, esto no es válido (C) Python; debe haber buenas razones para que esto no sea obvio para el intérprete CPython: ¿cuáles son estas razones? – EOL

3

No creo que if se pueda usar como un nombre de variable o un atributo (explícitamente), ya que es una palabra clave.

Puede, sin embargo, utilizar setattr y getattr de evitar esto de una manera desordenada

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

Sí, de hecho. Esto se ve incluso mejor que acceder a 'o .__ dict__'. Sin embargo, la pregunta es sobre cuáles son los motivos de esta restricción y si la restricción está documentada. – EOL

+0

La razón es porque no puede anular las palabras clave. Eso no necesita ser documentado. – Blender

+0

Me gusta la respuesta de @Cat Plus Plus en los comentarios principales. Fue una decisión de diseño para facilitar el analizador. La expresión idiomática python es 'if_', o' exec_', etc. – jdi

Cuestiones relacionadas