我目前正在开发一个关注性能的python项目,因为我的CPU始终使用其90%至98%的计算能力。
所以我在考虑如何更改代码以使其更快,并注意到我有一个字符串变量,该变量始终接收两个值之一:
state = "ok"
state = "notOk"
由于它只有2个值,因此我很难将其更改为类似boolean的值:
isStateOk = True
isStateOk = False
这样做有意义吗?将字符串归因于变量并将布尔值归因于变量的速度是否有很大差异,或根本没有差异?
我还应该提到,我在代码中使用了30个如果比较这个变量,那么也许比较速度会有所帮助吗?
if (state == "ok) # Original comparison
if (isStateOk) # New comparison
答案 0 :(得分:1)
那不会使用90-98%的CPU来修复程序,但是从技术上来说,使用布尔值会更好。
您也可以使用is instead of ==:
isStateOk = True
if isStateOk is True:
# Do stuff
编辑:
没关系,在https://hg.python.org/cpython/rev/01a7e66525c2/中,他们已经使== True
被Python解释器转换为引擎盖下的is True
,因此以任何一种方式编写都没有性能差异。
虽然在这里使用布尔值是个好主意,因为布尔值的目的是表示正常/不正常状态,但不会带来任何明显的性能改进。
答案 1 :(得分:1)
如另一个答案所述,这种微优化可能无法修复代码。可能你应该看看更一般的东西(算法、数据类型/结构以及在 Python 中有效使用它们的方法,例如使用 map/filter/reduce/list comprehensions 而不是 for 循环等)。
但是,关于您问题的血腥细节,请尝试运行以下测试:
import time
def measure_time(a_function, times):
start = time.perf_counter()
#for i in range(times):
a_function(times)
end = time.perf_counter()
print ("{0:40} {1}".format( a_function.__name__, end - start ) )
def test_strings_eq_literal(n):
stateOk = "ok"
stateNotOK = "notOK"
state = stateNotOK
for i in range(n):
state == "ok"
def test_strings_is_literal(n):
stateOk = "ok"
stateNotOk = "notOK"
state = stateNotOk
for i in range(n):
state is "ok" # careful with this - it works for simple, id-like strings only
def test_strings_eq(n):
stateOk = "ok"
stateNotOK = "notOK"
state = stateNotOK
for i in range(n):
state == stateOk
def test_strings_is(n):
stateOk = "ok"
stateNotOk = "notOK"
state = stateNotOk
for i in range(n):
state is stateOk # careful with this - it works for simple, id-like strings only
def test_bool_eq_literal(n):
stateOk = True
stateNotOk = False
state = stateNotOk
for i in range(n):
stateOk == True
def test_bool_is_literal(n):
stateOk = True
stateNotOk = False
state = stateNotOk
for i in range(n):
state is True
def test_bool_eq(n):
stateOk = True
stateNotOk = False
state = stateNotOk
for i in range(n):
stateOk == stateOk
def test_bool_is(n):
stateOk = True
stateNotOk = False
state = stateNotOk
for i in range(n):
state is stateOk
n = 100000000
measure_time( test_strings_eq_literal, n )
measure_time( test_strings_is_literal, n )
measure_time( test_strings_eq, n )
measure_time( test_strings_is, n )
measure_time( test_bool_eq_literal, n )
measure_time( test_bool_is_literal, n )
measure_time( test_bool_eq, n )
measure_time( test_bool_is, n )
我得到:
test_strings_eq_literal 3.6397838770062663
test_strings_is_literal 2.9926898650010116
test_strings_eq 3.7794520660536364
test_strings_is 3.0217343979747966
test_bool_eq_literal 3.4703008759533986
test_bool_is_literal 2.836865450022742
test_bool_eq 3.5056013059802353
test_bool_is 2.847688327950891
什么表明您使用 is
而不是 ==
获得最大收益(高达约 20%),即使使用一些字符串(但要小心 - is
仅适用于简单的/short id-like 字符串;你必须确定你在这里做什么;即使是解释器在其中一种情况下也会发出警告,所以最好不要这样做)。
相比之下,通过使用文字而不是变量似乎可以获得一点点(有点预期 - 必须在幕后额外完成一些取消引用层),但这并不值得关注。
在另一个答案中不太正确的地方(这实际上触发了我的回答)是布尔值和简单的类似 id 的字符串(并且只有这样!)都是 Python 中的单例对象,并且在性能上几乎没有区别像你这样的情况。但是,对于较长的字符串(带有空格等),情况不是 - 这样的字符串不能与 is
进行比较,并且将它们与 ==
进行比较会比使用布尔值。
但如上所述 - 不如先看看程序中更一般/基本的东西。仅仅改变这一点并不能解决您的问题。