我在写一个tic-tac-toe游戏,并使用一个枚举来表示三个结果——lose
,draw
,和{("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
这比简单地引用全局变量慢得多。在
^{pr2}$我的问题是:
你在计时循环。字符串文字本身被完全忽略:
这是一个什么也不做的函数。所以计时循环需要
0.024598151998361573
秒来运行一百万次。在在本例中,字符串实际上变成了
^{pr2}$f
函数的docstring:但是,如果没有赋值或者表达式的一部分,CPython通常会省略代码中的字符串:
这里的
1 + 1
被折叠成一个常量(2
),而字符串文本又一次消失了。在因此,不能将其与查找
enum
对象上的属性相比较。是的,查找属性需要周期。但查找另一个变量也是如此。如果您真的担心性能,您可以始终缓存属性查找:在}都是局部查找。在
timeit
测试中,所有变量都是局部变量,因此Result
和{enum
属性查找比“常规”属性查找花费的时间稍长:这是因为
enum
元类包含一个{a1},每次查找属性时都会调用它;enum
类的属性是在专门的字典中查找的,而不是在__dict__
类中查找。执行该钩子方法和附加属性查找(访问映射)都需要额外的时间:在一个井字游戏中,你一般不会担心什么是微不足道的时间差异。当人类玩家的速度比你的电脑慢几个数量级时就不会了。人类玩家不会注意到1.2微秒和0.024微秒之间的差别。在
相关问题 更多 >
编程相关推荐