来自 Perl 背景,我习惯于:
my @words = qw(fee fi fo fum);
我想知道以下 Python 是否会导致运行时性能下降:
words = 'fee fi fo fum'.split()
或者 ifwords
在编译时绑定。
来自 Perl 背景,我习惯于:
my @words = qw(fee fi fo fum);
我想知道以下 Python 是否会导致运行时性能下降:
words = 'fee fi fo fum'.split()
或者 ifwords
在编译时绑定。
dis
您可以使用该模块查看字节码:
>>> from dis import dis
>>>
>>> def f():
... words = 'fee fi fo fum'.split()
...
>>> dis(f)
2 0 LOAD_CONST 1 ('fee fi fo fum')
3 LOAD_ATTR 0 (split)
6 CALL_FUNCTION 0
9 STORE_FAST 0 (words)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
split
(由 加载LOAD_ATTR
)被调用 via并在运行时CALL_FUNCTION
将其结果分配给words
via 。STORE_FAST
换句话说,x.split()
即使x
是硬编码的字符串,也不会在编译时解析。
当然, using'fee fi fo fum'.split()
和它的结果之间的性能差异,即['fee', 'fi', 'fo', 'fum']
,将可以忽略不计,所以不要仅仅为了性能提升而从一个更改为另一个。
即使在 PERL 中也不能在编译时绑定它,因为每次通过该语句时都必须创建一个新的新列表。
换句话说,在 Python 中,当你看到
x = ['fee', 'fi', 'fo', 'fum']
代码不能只加载特定的对象地址,x
因为每次执行语句时它都必须是一个新的新列表对象。考虑
def foo():
return ['fee', 'fi', 'fo', 'fum']
x = foo()
x[0] = 'bar'
print foo()[0] # must be 'fee'
print x[0] # must be 'bar'
然而,Python 对不可变对象做了一些优化;例如:
def foo():
return (1, 2, 3)
实际上总是返回同一个对象(它不会每次都分配一个新的元组),并且对于
def foo():
return 3 * 4
它实际上返回 12 而不在运行时进行乘法运算。
但是,您的示例无法解决加载在编译时计算的常量,它必须至少是一个列表“文字”(这实际上是一个列表生成器,每次评估时都会创建一个新对象)。
IIRC 常量折叠仅在编译时针对数字/字符串上的二进制运算符进行,而不是针对任何函数调用(请注意,在 Python 中,即使是不好的做法,更改例如标准函数也是合法的len
,所以你不能确定len("foo")
总是返回 3)。
仅传递常量的标准字符串上的方法调用确实可以在编译时移动 IMO,但 AFAIK 目前还没有完成(而且这并不常见,因此可能不值得付出努力)。