>>> 1 .__hash__()
1
>>> 1.__hash__()
File "<stdin>", line 1
1.__hash__()
^
SyntaxError: invalid syntax
在此已经涵盖在此之前,第二个例子中不起作用,因为整型常量实际上解析为float。
我的问题是, 为什么Python解析,这个是一个int属性访问,当解释为float是一个语法错误? 上Docs部分词法分析似乎表明,只有当其他解释有歧义所需的空白,但也许我读这部分错误的。
在一个预感,好像词法分析器是贪婪(试图采取最大的令牌可能的),但我没有源出于此要求。
仔细阅读,它说
需要两个标记之间的空白仅当它们级联本来被解释为不同的令牌 (例如,ab是一个符号,但AB是两个符号)。
1.__hash__()
被标记化为:
import io, tokenize
for token in tokenize.tokenize(io.BytesIO(b"1.__hash__()").read):
print(token.string)
#>>> utf-8
#>>> 1.
#>>> __hash__
#>>> (
#>>> )
#>>>
Python的词法分析器会选择一个令牌,包括从左向右读时形成一个合法的标记,尽可能长的字符串 ; 解析没有两个令牌之后应该能够组合成一个有效的令牌。 其中的逻辑是非常相似在您的其他问题 。
混乱似乎无法识别标记化步骤作为一个完全独立的步骤。 如果语法允许分裂令牌只是为了让解析器快乐那么可以肯定你所期望
_ or1.
来标记为
_
or
1.
但目前还没有这样的规则,所以它作为标记化
_
or1
.
词法分析器是很简单的,不会走回头路。 语言解析器通常分为词法相和解析阶段,或词法分析器和解析器。 词法分析器打破了字符流成标记,然后分析器确定来自令牌的程序结构。 词法分析器看到的4个标记: 1.
, __hash__
, (
, )
:浮球,标识符,开括号,特写括号。 解析器不能让这些标记的意义,但并不意味着词法分析器会尝试不同的LEX的字符。
它只是定义的问题; 对语言语法做这项工作。
属性引用以比一个更广泛的级别定义浮点文字 。 因此,从语法水平,解析器必须承认1.
为浮点文字,而不是一个属性的参考。
当然,分析器可以到达时原路返回_
和揣摩,这不是一个浮点字面而是一个属性引用,而不是。 然而,由于CPython的解析器是LL(1)解析器回溯不是一个选项。 因此,语法将不得不改变了很多,让解析器认识到这一点(现在虽然我不知道,如果它甚至有可能与LL(1)语法分析器)。 我们还可以改变Python的解析器别的东西,也许一个不走回头路,但这样做不仅是一个非常艰巨的任务(它也需要改变语法),但会增加解析过程的复杂很多(与这可能会降低速度)。
因此, 也许这将是可能的,但它需要在语言规范的重大变化。 这本身是有问题的。 这也将打破现有的代码,利用这个早期识别浮动,例如1.if True else 0
。