获取整数和浮点数的属性

时间:2013-11-28 15:09:53

标签: python

我正在使用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文字的行为有所不同?

5 个答案:

答案 0 :(得分:30)

这可能是使用解析算法的结果。一个简单的心理模型是,标记生成器会尝试匹配所有标记模式,并识别它找到的最长匹配。在较低级别,标记化器逐个字符地工作,并且仅基于当前状态和输入字符做出决定 - 不应该有任何回溯或重新读取输入。

在使用公共前缀加入模式后 - 在这种情况下,int文字的模式和float文字模式的组成部分 - 在标记化程序中发生的是它:

  1. 读取1,并进入指示“正在阅读floatint字面值的状态
  2. 读取.,然后输入状态“阅读float字面值”
  3. 读取_float不能成为1.字面值的一部分。解析器将float作为_文字标记发出。
  4. __class__开始进行解析,最终将123abc作为标识符令牌发出。
  5.   

    旁白:这种标记化方法也是常见语言具有语法限制的原因。例如。身份标识   包含字母,数字和下划线,但不能以a开头   数字。如果允许,123可以作为一个   标识符,或整数abc后跟标识符<FloatLiteral: '1.'> <Identifier: '__class__'>

         

    类似于lex的标记器会认为这是前者,因为它会导致   最长的单一令牌,但没有人喜欢保留细节   在尝试阅读代码时,就像这样。或者在尝试时   为此问题编写和调试tokenizer。


    然后,解析器尝试处理令牌流:

    123abc

    在Python中, literal 后面直接跟着标识符 - 令牌之间没有运算符 - 没有任何意义,所以解析器会失败。这也意味着Python抱怨a语法无效的原因不是标记化器错误“字符abc在整数文字中无效”,而是解析器错误“标识符123无法直接跟随整数文字1


    令牌系统无法将int识别为float字面值的原因是使 的字符 int - 或 - . 状态确定它刚刚读取的内容。如果它是float,则它是int字面值的开头,之后可能会继续。如果它是其他内容,则它是一个完整的float文字标记。

    标记器不可能“返回”并重新读取先前的输入作为其他内容。实际上,令牌化程序的级别太低而无法关注“属性访问”是什么并处理这种歧义。


    现在,您的第二个示例是有效的,因为标记生成器知道.文字只能有一个.。更确切地说:第一个float使其从 int - 或 - float 状态转换为 E 州。在这种状态下,它只需要数字(或j表示科学/工程符号,float表示复数...)继续.字面值。不是数字等的第一个字符(即float)肯定不再是<FloatLiteral: '1.'> <Operator: '.'> <Identifier: '__class__'> 文字的一部分,并且标记生成器可以发出完成的标记。因此,第二个示例的令牌流将是:

    string

    当然,解析器会识别为有效的Python。现在我们也知道为什么建议的解决方法会有所帮助。在Python中,用空格分隔标记是可选的 - 与Lisp不同。相反,空格确实分隔标记。 (也就是说,除了1 .__class__ 文字之外,没有任何标记可能包含空格,它只是在标记之间跳过。)所以代码:

    <IntLiteral: '1'> <Operator: '.'> <Identifier: '__class__'>
    

    始终被标记为

    int

    由于右括号不能出现在(1).__class__ 字面值中,因此:

    <Operator: '('> <IntLiteral: '1'> <Operator: ')'> <Operator: '.'> <Identifier: '__class__'>
    

    被读为:

    1..__class__ # => <type 'float'>
    

    以上暗示,有趣的是,以下内容也是有效的:

    float

    .字面值的小数部分是可选的,第二个{{1}}读取将使前面的输入被识别为一个。

答案 1 :(得分:27)

这是一个标记化问题...... .被解析为浮点数的小数部分的开头。

您可以使用

(1).__class__

避免问题

答案 2 :(得分:10)

因为如果在数字之后有.,python会认为你正在创建一个浮点数。当遇到其他不是数字的东西时,它会抛出错误。

但是,在float中,python不期望另一个.成为值的一部分,因此结果!有用。 :)

我们如何获取属性呢?

您可以轻松地将其包装在括号中。例如,请参阅此控制台会话:

>>> (1).__class__
<type 'int'>

现在,Python知道你不是要创建一个浮点数,而是要引用int本身。

奖励:在号码工作之后加上一个空格。

>>> 1 .__class__
<type 'int'>

另外,如果您只想获得__class__type(1)会为您完成。

希望这有帮助!

答案 3 :(得分:4)

或者你甚至可以这样做:

>>> getattr(1 , '__class__')
<type 'int'>

答案 4 :(得分:3)

您需要用括号括起数字:

>>> (1).__class__
<type 'int'>
>>>

否则,Python会在数字后面看到.,并尝试将整个事物解释为浮点数。