获取整数和浮点数的属性

aja*_*jay 18 python

我正在使用Python解释器(Python 3.2.3)并尝试以下方法:

>>> dir(1)
Run Code Online (Sandbox Code Playgroud)

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

>>> 1.__class__
Run Code Online (Sandbox Code Playgroud)

然而,这引发了一个例外:

File "<stdin>", line 1
1.__class__
          ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

当我尝试使用浮子时,我得到了我的预期:

>>> 2.0.__class__
<class 'float'> 
Run Code Online (Sandbox Code Playgroud)

为什么intfloat文字表现不同?

mil*_*ose 30

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

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

  1. 读取1,并进入指示"读取一个float或一个int字面"的状态
  2. 读取.,并进入"阅读float文字"状态
  3. 读取_,不能成为float文字的一部分.解析器1.作为float文字标记发出.
  4. 从开始进行解析_,最终__class__作为标识符令牌发出.

旁白:这种标记化方法也是常见语言具有语法限制的原因.例如,标识符包含字母,数字和下划线,但不能以数字开头.如果允许,123abc可以将其作为标识符,或者123后跟标识符的整数abc.

类似于lex的标记器会将此识别为前者,因为它会导致最长的单个令牌,但是没有人喜欢在尝试读取代码时必须保留这样的细节.或者在尝试编写和调试令牌化器时.


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

<FloatLiteral: '1.'> <Identifier: '__class__'>
Run Code Online (Sandbox Code Playgroud)

在Python中,直接后跟标识符文字 - 在标记之间没有运算符 - 没有任何意义,因此解析器保释.这也意味着Python抱怨语法无效的原因不是令牌化程序错误"字符在整数文字中无效",而是解析器错误"标识符不能直接跟随整数字面"123abcaabc123


为什么标记生成器无法识别的原因1作为一个int字面的是,这使得它的角色离开float-或者int状态决定了它只是阅读.如果是的话.,那就是float文字的开头,之后可能会继续.如果它是别的东西,它是一个完整的int文字标记.

令牌化器不可能"返回"并重新读取先前的输入作为其他内容.实际上,令牌化器的级别太低而无法关注"属性访问"是什么并处理这种模糊性.


现在,您的第二个示例是有效的,因为tokenizer知道float文字只能包含一个文字..更确切地说:第一个.使它从float- 或 -int状态转变为float状态.在这种状态下,它只需要数字(或E科学/工程符号,j复数数字......)继续float文字.不是数字等的第一个字符(即.)肯定不再是float文字的一部分,而令牌化器可以发出完成的令牌.因此,第二个示例的令牌流将是:

<FloatLiteral: '1.'> <Operator: '.'> <Identifier: '__class__'>
Run Code Online (Sandbox Code Playgroud)

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

1 .__class__
Run Code Online (Sandbox Code Playgroud)

总是被标记为

<IntLiteral: '1'> <Operator: '.'> <Identifier: '__class__'>
Run Code Online (Sandbox Code Playgroud)

由于右括号不能出现在int文字中,因此:

(1).__class__
Run Code Online (Sandbox Code Playgroud)

得到如下:

<Operator: '('> <IntLiteral: '1'> <Operator: ')'> <Operator: '.'> <Identifier: '__class__'>
Run Code Online (Sandbox Code Playgroud)

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

1..__class__ # => <type 'float'>
Run Code Online (Sandbox Code Playgroud)

float文字的小数部分是可选的,第二次.读取将使前面的输入被识别为一个.


650*_*502 27

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

您可以使用

(1).__class__
Run Code Online (Sandbox Code Playgroud)

避免这个问题

  • 或者在`1`之后留空:`1 .__ class__` (9认同)

aIK*_*Kid 10

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

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

那么我们如何获得属性呢?

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

>>> (1).__class__
<type 'int'>
Run Code Online (Sandbox Code Playgroud)

现在,Python知道你不是要创建一个float,而是要引用int本身.

奖励:在号码起作用后放一个空格.

>>> 1 .__class__
<type 'int'>
Run Code Online (Sandbox Code Playgroud)

此外,如果你只想获得__class__,type(1)将为你做.

希望这可以帮助!