我正在使用Python解释器(Python 3.2.3)并尝试以下方法:
>>> dir(1)
这给了我int对象的所有属性和方法。接下来我尝试了:
>>> 1.__class__
然而,这引起了例外:
File "<stdin>", line 1
1.__class__
^
SyntaxError: invalid syntax
当我尝试使用浮子时,我得到了我的预期:
>>> 2.0.__class__
<class 'float'>
为什么int
和float
文字的行为有所不同?
答案 0 :(得分:30)
这可能是使用解析算法的结果。一个简单的心理模型是,标记生成器会尝试匹配所有标记模式,并识别它找到的最长匹配。在较低级别,标记化器逐个字符地工作,并且仅基于当前状态和输入字符做出决定 - 不应该有任何回溯或重新读取输入。
在使用公共前缀加入模式后 - 在这种情况下,int
文字的模式和float
文字模式的组成部分 - 在标记化程序中发生的是它:
1
,并进入指示“正在阅读float
或int
字面值的状态 .
,然后输入状态“阅读float
字面值” _
,float
不能成为1.
字面值的一部分。解析器将float
作为_
文字标记发出。__class__
开始进行解析,最终将123abc
作为标识符令牌发出。旁白:这种标记化方法也是常见语言具有语法限制的原因。例如。身份标识 包含字母,数字和下划线,但不能以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会在数字后面看到.
,并尝试将整个事物解释为浮点数。