use*_*548 1 python coding-style python-3.x
为什么我问这个问题,因为我总是担心这种风格的代码
def callsomething(x):
if x in (3,4,5,6):
#do something
Run Code Online (Sandbox Code Playgroud)
如果函数调用的东西经常被调用,那么(3,4,5,6)是否浪费了太多的空间和时间?在某些语言如C中,它可能被推入数据段,如常量,但在python中,我不知道它是如何工作的,所以我倾向于编写这样的代码
checktypes = (3,4,5,6)#cache it
def callsomething(x):
global checktypes
if x in checktypes:
#do something
Run Code Online (Sandbox Code Playgroud)
但经过测试我发现这种方式使程序变慢,在更复杂的情况下,代码将是这样的:
types = (3,4,5,6)
def callsomething(x):
global types
for t in types:
t += x
#do something
Run Code Online (Sandbox Code Playgroud)
仍然比这慢
def callsomething(x):
for t in (3+x,4+x,5+x,6+x):
#do something
Run Code Online (Sandbox Code Playgroud)
在这种情况下,程序必须创建(3 + x,4 + x,5 + x,6 + x),对吧?但它仍然比第一个版本更快,但不是太多了.
我知道python中的全局var访问会减慢程序,但它与创建结构的比较有多大?
别担心,它存储为常量(这解释了为什么它比你预期的更快)
>>> def callsomething(x):
... if x in (3,4,5,6): pass
...
>>> import dis
>>> dis.dis(callsomething)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 5 ((3, 4, 5, 6))
6 COMPARE_OP 6 (in)
9 POP_JUMP_IF_FALSE 15
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
仰望x一个set应该更快,对吗?但是呃哦......
>>> def callsomething(x):
... if x in {3,4,5,6}: pass
...
>>> dis.dis(callsomething)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (3)
6 LOAD_CONST 2 (4)
9 LOAD_CONST 3 (5)
12 LOAD_CONST 4 (6)
15 BUILD_SET 4
18 COMPARE_OP 6 (in)
21 POP_JUMP_IF_FALSE 27
24 JUMP_FORWARD 0 (to 27)
>> 27 LOAD_CONST 0 (None)
30 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
set是可变的,所以Python直到最近才进行这种优化.Python3.3认为将其变为冻结集是安全的
Python 3.3.0 (default, Sep 29 2012, 17:17:45)
[GCC 4.7.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def callsomething(x):
... if x in {3,4,5,6}: pass
...
>>> import dis
>>> dis.dis(callsomething)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 5 (frozenset({3, 4, 5, 6}))
6 COMPARE_OP 6 (in)
9 POP_JUMP_IF_FALSE 15
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
>>>
Run Code Online (Sandbox Code Playgroud)