我正在使用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)
为什么int和float文字表现不同?
mil*_*ose 30
这可能是使用解析算法的结果.一个简单的心理模型是,标记生成器尝试匹配所有标记模式,并识别它找到的最长匹配.在较低级别,标记化器逐个字符地工作,并且仅基于当前状态和输入字符做出决定 - 不应该有任何回溯或重新读取输入.
在使用公共前缀连接模式之后 - 在这种情况下,int文字的模式和float文字模式的组成部分- 在标记化器中发生的是它:
1,并进入指示"读取一个float或一个int字面"的状态.,并进入"阅读float文字"状态_,不能成为float文字的一部分.解析器1.作为float文字标记发出._,最终__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)
避免这个问题
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)将为你做.
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
1629 次 |
| 最近记录: |