我想知道以下两个代码片段有什么区别:
float_var = 1234.5678
a = int(float_var)
b = (int)(float_var)
它们都成功地将变量转换为整数(至少在 Python 3.6 中,我不知道 2.7 是否支持这种行为),但在语法上存在明显差异。此外,以下代码段失败:
c = (int)float_var
这让我相信变量名称(或文字,因为它可能是)必须括在括号中。
从我可以收集到的两个示例中的区别是,第一个通过将参数传递到其__init__方法来创建类的新实例。而在第二个示例中,由于 int 对象定义了一个方法__float__,因此它可以将任何浮点数"强制转换"到 int 的实例。
我这样想对吗?另外,为什么第三个示例失败了?我不明白为什么需要括号来包围"转换"的值。
没有区别。
Python 类型是对象,可以像函数一样调用。int(foo)
语法可能由Python和C共享,但相似之处到此为止。
在您的代码中,int == (int) == ((int))
都以相同的方式相等1 + 1 == (1 + 1) == ((1 + 1))
.如果你看一下字节码,Python对两者的处理方式相同:
In [42]: dis.dis(lambda: (int)(a))
1 0 LOAD_GLOBAL 0 (int)
3 LOAD_GLOBAL 1 (a)
6 CALL_FUNCTION 1
9 RETURN_VALUE
In [43]: dis.dis(lambda: int(a))
1 0 LOAD_GLOBAL 0 (int)
3 LOAD_GLOBAL 1 (a)
6 CALL_FUNCTION 1
9 RETURN_VALUE
第三个例子失败了,因为Python不是C。你得到一个SyntaxError
,因为它不是有效的 Python 代码。
我这样想对吗?
不。括号把你甩开了。这两种方法是等效的。这:
(int)(float_var)
与此相同:
int(float_var)
这不是一些特殊的"强制转换"语法。它只是一个名字周围的括号。Python 语法允许这样做:
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
解析器为每个方法返回一个等效的抽象语法树:
>>> import ast
>>> ast.dump(ast.parse('(int)(float_var)'))
"Module(body=[Expr(value=Call(func=Name(id='int', ctx=Load()), args=[Name(id='float_var', ctx=Load())], keywords=[]))])"
>>> ast.dump(ast.parse('int(float_var)'))
"Module(body=[Expr(value=Call(func=Name(id='int', ctx=Load()), args=[Name(id='float_var', ctx=Load())], keywords=[]))])"
但是,Python 语法不允许使用第三种方法。如上所述,名称周围的括号没什么特别的。无论哪种方式,它都会转换为函数调用。因此,虽然int
周围的括号是可选的,但末尾的括号不是。
a和b之间没有区别,说它们不同就像说2
和(2)
是不同的。第三个示例失败,因为不能在没有括号的情况下调用函数。例如,int 5
将不起作用,因为参数周围没有括号。