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

Fil*_*efp 52 python language-lawyer python-2.7 python-3.x

我已经读过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
Run Code Online (Sandbox Code Playgroud)
  • 为什么something.__str__()除了"一切"之外还要工作int
  • 123不是一个对象类型的int

Ned*_*der 88

你需要parens:

(4).__str__()
Run Code Online (Sandbox Code Playgroud)

问题是词法分析员认为"4".将成为一个浮点数.

此外,这有效:

x = 4
x.__str__()
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢在空间中使用括号. (2认同)

Fil*_*efp 49

所以你认为你可以 跳舞 浮点?

123就像一个对象一样3.14,"问题"在于语言的语法规则; 解析器认为我们要定义一个float - 而不是一个带尾随方法调用的int.

如果我们将数字括在括号中,我们将得到预期的行为,如下所示.

>>> (123).__str__()
'123'
Run Code Online (Sandbox Code Playgroud)

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

>>> 123 .__str__()
'123'
Run Code Online (Sandbox Code Playgroud)


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

>>> 123.__str__()
  File "", line 1
    123.__str__()
              ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

解析器试图解释__str__()为一个数字序列,但显然失败-我们得到的SyntaxError基本上说解析器在的东西,没想到偶然.



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

123.__str__()
^^^ - int
Run Code Online (Sandbox Code Playgroud)
123.__str__()
^^^^- start of floating-point
Run Code Online (Sandbox Code Playgroud)

正如一个小孩子想要在他们的盘子上尽可能多的蛋糕,解析器是贪婪的,并且想尽可能多地吞下 - 即使这并不总是最好的想法 - 如后者选择("更好")替代方案.

当它后来意识到它__str__()决不能被解释为浮点小数时,它已经太晚了; SyntaxError.

注意

 123 .__str__() # works fine
Run Code Online (Sandbox Code Playgroud)

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

注意

 123..__str__() # works fine
Run Code Online (Sandbox Code Playgroud)

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



对于语言律师

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

词法分析 - 2.4.5浮点文字

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

词法分析 - 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"
Run Code Online (Sandbox Code Playgroud)


Sve*_*ach 41

在以下后面添加一个空格4:

4 .__str__()
Run Code Online (Sandbox Code Playgroud)

否则,将词法分析器这个表达式分成令牌"4.","__str__","("")",即第一令牌被解释为一个浮点数.词法分析器总是尝试构建最长的令牌.

  • @Abderrahimben:大多数编程语言的词法分析者通过构建最长的令牌来工作.具有模糊标记化的情况通常很少并且应该避免,并且尝试自动解决模糊性会使词法分析器显着复杂化.`4.`是一个有效的浮点数,它是我所知道的所有编程语言,包括Python. (4认同)
  • @SvenMarnach一个例外的当前编程语言是C#.它使`4`成为`int`类型的有效文字,而`4.0`是类型`double`的有效文字,但是`4.`是两个单独的标记.这样,'double d = 4.;`是不允许的,但用户可以简单地写`double d = 4.0;`.这样,`string s = 4.ToString();`*是*允许的.(你确实说过"你知道的所有编程语言",所以如果你不知道C#,你就没有错,但它可能是其他人的有用补充.) (4认同)

kra*_*nko 6

实际上(增加不可读性......):

4..hex()
Run Code Online (Sandbox Code Playgroud)

也是有效的.它给了'0x1.0000000000000p+2'- 但是当然它是一个漂浮物,当然......