为什么class属性不能在python中命名为保留字?

Why can't class attributes be named as reserved words in python?

在python中似乎不能使用保留字作为属性:

$ python
Python 3.6.2 |Continuum Analytics, Inc.| (default, Jul 20 2017, 13:51:32) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
>>>     global = 3
  File "<stdin>", line 2
    global = 3
           ^
SyntaxError: invalid syntax

这似乎是明智的,因为它是模棱两可的:我在这里使用 global 关键字吗?很难说。

但这不是明智的恕我直言:

>>> class A: pass
>>> a = A()
>>> a.global = 3
  File "<stdin>", line 1
    a.global = 3
           ^
SyntaxError: invalid syntax
>>> a.def = 4
  File "<stdin>", line 1
    a.def = 4
        ^
SyntaxError: invalid syntax
>>> a.super = 5
>>> a.abs = 3
>>> a.set = 5
>>> a.False = 5
  File "<stdin>", line 1
    a.False = 5
          ^
SyntaxError: invalid syntax
>>> a.break = 5
  File "<stdin>", line 1
    a.break = 5
          ^
SyntaxError: invalid syntax

为什么有这个限制?我不是孤立地使用保留字,而是作为 class 属性:根本没有歧义。为什么 python 会关心这个?

这根本不值得。

当然,你可以允许它。破解标记器和解析器,以便标记器知道解析上下文并在解析器期望属性访问时发出 NAME 标记而不是关键字标记,或者只是让它始终在 DOT 之后发出 NAME 标记而不是关键字。但这会给你带来什么?

您会使解析器和分词器变得更复杂,因此更容易出错。你会让人类更难阅读 reader。你会限制未来的语法可能性。

你会造成混乱
Foo.for = 3

解析并

class Foo:
    for = 3

抛出语法错误。你会使 Python 变得不那么一致,更难学习,更难理解。

尽管如此,您将获得...写作 x.for = 3 的能力。我能说的最好的是它可以防止像 x.fibble = 3 这样的东西在添加 fibble 关键字时中断,但即便如此, fibble 的所有其他使用仍然会中断。不值得。如果你想使用疯狂的属性名称,你有 setattrgetattr.


Python 尽最大努力使语法简单。它的解析器是 LL(1),LL(1) 解析器的限制被认为是有益的 specifically because they prevent going overboard with crazy grammar rules:

Simple is better than complex. This idea extends to the parser. Restricting Python's grammar to an LL(1) parser is a blessing, not a curse. It puts us in handcuffs that prevent us from going overboard and ending up with funky grammar rules like some other dynamic languages that will go unnamed, such as Perl.

类似 x.for = 3 的内容不符合该设计理念。

要了解此限制背后的原因,您需要了解计算机语言的工作原理。

最初,您有一个文本文件。您将此文本提供给字符串分词器(称为词法分析器),该分词器可识别单词、运算符、注释、数字、字符串等词汇元素。基本上,词法分析器除了字符之外什么都不知道。它将文本文件转换为类型标记流。

然后将此标记流送入解析器。解析器处理更高级别的构造,例如方法定义、class 定义、导入语句等。例如,解析器知道函数定义以 "def" 开头,后跟一些名称(标识符类型的标记),然后是一个冒号,以及一堆缩进线。这意味着某些词如 "def"、"return"、"if" 是为解析器保留的,因为它们是语言语法的一部分。

解析的结果是一个叫做抽象语法树(AST)的数据结构。 AST直接对应文本文件的内容和结构。在 AST 中,没有关键字,因为它们已经达到了目的。另一方面,标识符(变量和函数的名称等)被保留,因为稍后 compiler/interpreter.

需要它们

简而言之,关键字的存在是为了赋予文本结构。没有结构,程序就不可能确定性地分析文本。如果您尝试将关键字用于其他内容,则会破坏结构。分析完结构后,就不再需要它们了。从本质上讲,这意味着语言的作者必须画一条线并为结构保留一些词,同时将所有其他词留给程序员使用。

这不仅仅是 Python 特有的。每种语言都一样。如果您没有文本文件,则不需要关键字。从技术上讲,一种语言有可能克服这个限制,但它会使事情复杂化很多,而没有任何实际好处。将解析器与其他语言分开非常有意义,以至于您不希望以任何其他方式使用它。