访问文字的属性适用于所有类型,但不适用于`int`;为什么?[重复]


问题内容

这个问题已经在这里有了答案

为什么“ 1.real”是语法错误,而“ 1.real”在Python中有效? (3个答案)

去年关闭。

我已经读到python中的所有内容都是一个对象,因此我开始尝试不同的类型并对其进行调用 __str__ -起初我感到非常兴奋,但后来我感到困惑。

>>> "hello world".__str__()
'hello world'
>>> [].__str__()
'[]'
>>> 3.14.__str__()
'3.14'
>>> 3..__str__()
'3.0'
>>> 123.__str__()
  File "<stdin>", line 1
    123.__str__()
              ^
SyntaxError: invalid syntax
  • 为什么还要_something_.__str__()为“一切”工作int
  • 123不是一个 对象 类型的int

问题答案:

所以您认为您可以 跳舞 浮点数?

123和问题一样多3.14,“问题”位于语言的语法规则之内;解析器认为我们将要定义一个 float —而不是带有尾随方法调用的 int

如果将数字包装在括号中,则将获得预期的行为,如下所示。

>>> **(123).__str__()**
'123'

或者,如果我们只是在后面添加一些空格 123

>>> **123 .__str__()**
'123'

它不工作的原因123.__str__()是, 下面的 123 解释为 小数点 的某些部分宣布 浮点

>>> **123.__str__()**
  File "", line 1
    123.__str__()
              ^
SyntaxError: invalid syntax

解析器尝试将其解释__str__()为数字序列,但显然失败了,并且我们得到了 SyntaxError, 基本上是说解析器偶然发现了它没有想到的东西。


细化

当在寻找123.__str__()蟒解析器可以使用任一 3 个字符和解释这些 3 个字符为 整数或者 它可以使用 4个
字符和解释这些作为 开始 一个的 浮点

123.__str__()
^^^ - int



123.__str__()
^^^^- start of floating-point

就像一个小孩子想在盘子上放尽可能多的蛋糕一样,解析器很贪婪,并且想一次吞下尽可能多的东西,即使这并不总是最好的主意,例如后者(“更好”)选择。

当它后来意识到__str__()绝不能解释为 浮点数小数时 ,已经为时已晚。 语法错误

注意

 123 .__str__() # works fine

在上面的代码段中,123(请注意空格)必须解释为 整数, 因为没有 数字
可以包含空格。这意味着它在语义上等同于(123).__str__()

注意

 123..__str__() # works fine

上面的方法也有效,因为一个 数字最多 可以包含一个 小数点 ,这意味着它等于(123.).__str__()


对于 语言律师

本节包含相关文字的词汇定义。

词法分析-2.4.5浮点文字

floatnumber   ::=  pointfloat | exponentfloat
pointfloat    ::=  [intpart] fraction | intpart "."
exponentfloat ::=  (intpart | pointfloat) exponent
intpart       ::=  digit+
fraction      ::=  "." digit+
exponent      ::=  ("e" | "E") ["+" | "-"] digit+

词法分析-2.4.4整数文字

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"+
nonzerodigit   ::=  "1"..."9"
digit          ::=  "0"..."9"
octinteger     ::=  "0" ("o" | "O") octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
octdigit       ::=  "0"..."7"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"
bindigit       ::=  "0" | "1"