Eli*_*ICA 8 python performance enums python-3.4
我在写一个井字棋游戏,并使用枚举来表示三种结果- lose
,draw
和win
.我认为这比使用字符串("lose", "win", "draw")
表示这些值更好.但使用枚举给我带来了显着的性能影响.
这是一个最小的例子,我只是引用其中一个Result.lose
或文字字符串lose
.
import enum
import timeit
class Result(enum.Enum):
lose = -1
draw = 0
win = 1
>>> timeit.timeit('Result.lose', 'from __main__ import Result')
1.705788521998329
>>> timeit.timeit('"lose"', 'from __main__ import Result')
0.024598151998361573
Run Code Online (Sandbox Code Playgroud)
这比简单地引用全局变量要慢得多.
k = 12
>>> timeit.timeit('k', 'from __main__ import k')
0.02403248500195332
Run Code Online (Sandbox Code Playgroud)
我的问题是:
Mar*_*ers 10
你正在计时定时循环.完全忽略字符串文字:
>>> import dis
>>> def f(): "lose"
...
>>> dis.dis(f)
1 0 LOAD_CONST 1 (None)
3 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
这是一个什么也不做的函数在所有.因此,定时循环需要0.024598151998361573
几秒钟才能运行100万次.
在这种情况下,字符串实际上成为f
函数的文档字符串:
>>> f.__doc__
'lose'
Run Code Online (Sandbox Code Playgroud)
但是CPython通常会在代码中省略字符串文字(如果未分配)或表达式的其他部分:
>>> def f():
... 1 + 1
... "win"
...
>>> dis.dis(f)
2 0 LOAD_CONST 2 (2)
3 POP_TOP
3 4 LOAD_CONST 0 (None)
7 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
在这里1 + 1
折叠成一个常量(2
),字符串文字再次消失.
因此,您无法将其与查找enum
对象上的属性进行比较.是的,查找属性需要循环.但查找另一个变量也是如此.如果您真的担心性能,可以随时缓存属性查找:
>>> import timeit
>>> import enum
>>> class Result(enum.Enum):
... lose = -1
... draw = 0
... win = 1
...
>>> timeit.timeit('outcome = Result.lose', 'from __main__ import Result')
1.2259576459764503
>>> timeit.timeit('outcome = lose', 'from __main__ import Result; lose = Result.lose')
0.024848614004440606
Run Code Online (Sandbox Code Playgroud)
在timeit
测试中所有变量都是本地人,所以无论Result
和lose
本地查找.
enum
属性查找确实比"常规"属性查找花费更多时间:
>>> class Foo: bar = 'baz'
...
>>> timeit.timeit('outcome = Foo.bar', 'from __main__ import Foo')
0.04182224802207202
Run Code Online (Sandbox Code Playgroud)
那是因为enum
元类包含每次查找属性时调用的专用__getattr__
钩子 ; enum
类的属性在专用字典而不是类中查找__dict__
.执行该钩子方法和附加属性查找(访问地图)都需要额外的时间:
>>> timeit.timeit('outcome = Result._member_map_["lose"]', 'from __main__ import Result')
0.25198313599685207
>>> timeit.timeit('outcome = map["lose"]', 'from __main__ import Result; map = Result._member_map_')
0.14024519600206986
Run Code Online (Sandbox Code Playgroud)
在Tic-Tac-Toe的游戏中,您通常不会担心无关紧要的时间差异.当人类播放器比计算机慢几个数量级时.人类玩家不会注意到1.2微秒或0.024微秒之间的差异.
归档时间: |
|
查看次数: |
515 次 |
最近记录: |