为什么属性名称不能是Python关键字?

时间:2012-03-17 02:51:41

标签: python attributes syntax-error

Python中的属性访问语法存在限制(至少在CPython 2.7.2实现中):

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

我的问题有两个:

  1. 是否存在禁止使用Python关键字属性名称(如o.if = 123中)的根本原因?
  2. 是否/上述对属性名称的限制记录在哪里?
  3. 在我的某个程序中执行o.class = …是有意义的,我对它无法做到有点失望(o.class_会起作用,但看起来并不那么简单)。

    PS :问题显然是ifclass是Python关键字。问题是为什么使用关键字作为属性名称将被禁止(我没有看到表达式o.class = 123中有任何歧义),以及这是否记录

2 个答案:

答案 0 :(得分:8)

因为当关键字总是关键字而不是上下文时,解析器更简单(例如if在语句级别时是一个关键字,而在表达式中只是一个标识符 - 对于if它来说由于X if C else Y而加倍,并且for用于列表推导和生成器表达式。)

因此,代码甚至没有达到属性访问的程度,它只是被解析器拒绝,就像错误的缩进一样(这就是为什么它是SyntaxError而不是AttributeError或者东西)。它不区分您是使用if作为属性名称,变量名称,函数名称还是类型名称。它永远不会是一个标识符,只是因为解析器总是为它分配“关键字”标签并使其成为与标识符不同的标记。

在大多数语言中都是一样的,语言语法(+ lexer规范)就是这方面的文档。 Language spec mentions it explicitly。它在Python 3中也没有变化。

另外,仅仅因为您可以使用setattr__dict__制作带有保留名称的属性,并不意味着应该。不要强迫自己/ API用户使用getattr而不是自然属性访问。当需要访问变量属性名称时,应保留getattr

答案 1 :(得分:1)

因为if是关键字。您对o.whileo.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

Python中的其他关键字可以通过以下方式获得:

>>> 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']

你应该通常在Python中使用关键字作为变量名。

我建议选择一个更具描述性的名称,例如iface如果是界面,或infld表示输入字段,等等。

至于你的问题编辑为什么不允许关键字,如果词汇元素没有上下文,它会极大地简化解析器。必须在某些地方将词法标记if视为关键字而在其他地方将标识符视为其他标识符,如果您更明智地选择标识符,则会引入并非真正需要的复杂性。

例如,C ++语句:

long int int = char[new - int];

可以(有点困难)使用复杂的解析器进行评估,该解析器基于这些词法元素出现的位置(以及它们两侧存在的内容)。但是,(至少部分地)为了简单(和可读性),这没有做到。