python - 获取整数和 float 的属性

标签 python

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





Why doesn't 2.__add__(3) work in Python?

(2 个回答)


7年前关闭。




我在玩 Python 解释器(Python 3.2.3)并尝试了以下操作:

>>> dir(1)

这给了我 int 对象的所有属性和方法。接下来我尝试:
>>> 1.__class__

然而,这引发了一个异常:
File "<stdin>", line 1
1.__class__
          ^
SyntaxError: invalid syntax

当我用浮点数尝试相同时,我得到了我的预期:
>>> 2.0.__class__
<class 'float'> 

为什么要intfloat文字的行为不同?

最佳答案

这可能是所使用的解析算法的结果。一个简单的心智模型是分词器尝试匹配 全部 存在的 token 模式,并识别 最长 匹配它找到。在较低级别上,分词器逐个字符地工作,并且仅根据当前状态和输入字符做出决定——不应有任何回溯或重新读取输入。

加入具有公共(public)前缀的模式后——在本例中,是 int 的模式文字和 float 模式的组成部分文字 – 在分词器中发生的事情是:

  • 阅读 1 ,并进入指示“正在读取 floatint 文字”
  • 的状态
  • 阅读 . ,并进入状态“阅读 float 文字”
  • 阅读 _ ,不能是 float 的一部分文字。解析器发出 1.作为 float文字标记。
  • _ 开始继续解析,并最终发出 __class__作为标识符 token 。

  • Aside: This tokenizing approach is also the reason why common languages have the syntax restrictions they have. E.g. identifiers contain letters, digits, and underscores, but cannot start with a digit. If that was allowed, 123abc could be intended as either an identifier, or the integer 123 followed by the identifier abc.

    A lex-like tokenizer would recognize this as the former since it leads to the longest single token, but nobody likes having to keep details like this in their head when trying to read code. Or when trying to write and debug the tokenizer for that matter.



    然后解析器尝试处理 token 流:
    <FloatLiteral: '1.'> <Identifier: '__class__'>
    

    在 Python 中,直接后跟标识符的文字——在标记之间没有运算符——是没有意义的,所以解析器会保释。这也意味着Python会提示123abc的原因。语法无效不是分词器错误“字符 a 在整数文字中无效”,而是解析器错误“标识符 abc 不能直接跟在整数文字 123 后面”

    分词器无法识别1的原因作为 int文字是使它 的字符离开 float -或- int状态决定了它刚刚读取的内容。如果是 . ,这是 float 的开始字面意思,之后可能会继续。如果是别的东西,那就是一个完整的int文字标记。

    分词器不可能“返回”并将先前的输入重新读取为其他内容。事实上,tokenizer 的级别太低,无法关心“属性访问”是什么并处理这种歧义。

    现在,您的第二个示例是有效的,因为标记器知道 float文字只能有一个 .在里面。更准确地说:第一个.使其从 float 过渡-或- int状态到 float状态。在这种状态下,它只需要数字(或 E 用于科学/工程符号, j 用于复数......)继续 float文字。第一个不是数字等的字符(即 . )绝对不再是 float 的一部分文字和分词器可以发出完成的标记。因此,您的第二个示例的 token 流将是:
    <FloatLiteral: '1.'> <Operator: '.'> <Identifier: '__class__'>
    

    当然,解析器随后将其识别为有效的 Python。现在我们也足够了解为什么建议的解决方法会有所帮助。在 Python 中,用空格分隔标记是 可选 – 不像,比如说,在 Lisp 中。相反,空格 是否单独的 token 。 (也就是说,除了 string 文字之外没有任何标记可能包含空格,它只是在标记之间跳过。)所以代码:
    1 .__class__
    

    总是被标记为
    <IntLiteral: '1'> <Operator: '.'> <Identifier: '__class__'>
    

    并且由于右括号不能出现在 int 中字面意思,这个:
    (1).__class__
    

    读作如下:
    <Operator: '('> <IntLiteral: '1'> <Operator: ')'> <Operator: '.'> <Identifier: '__class__'>
    

    以上暗示,有趣的是,以下内容也是有效的:
    1..__class__ # => <type 'float'>
    
    float的小数部分文字是可选的,第二个 . read 将使前面的输入被识别为一个。

    关于python - 获取整数和 float 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20269435/

    相关文章:

    python - 在 Python 中使用 Rpy2 对具有翻转坐标的 ggplot2 条形图进行排序

    python - Python 正则表达式中的正斜杠

    python - 在 include 中使用命名空间有什么意义? ( Django 2.0)

    Python:Scrapy 蜘蛛不返回结果?

    python - 为什么 pos_tag() 如此缓慢且可以避免?

    python - 使用 PyQt5/QtDesigner 弹出窗口或多个窗口

    python - 缓冲数据在达到输出大小限制后被截断

    python - 在类中定义函数时如何获取参数?

    python - 查找相机矩阵的翻译

    Python、Windows 和多处理