import time
def not_igual():
if not x == 'val':
x
def distinto():
if x != 'val':
x
def igual_else():
if x == 'val':
pass
else:
x
def test(tam):
inicio = time.time()
i = 0
while (i<tam) :
i = i + 1
fin = time.time()
vacio = fin-inicio
inicio = time.time()
i = 0
while (i<tam) :
not_igual()
i = i + 1
fin = time.time()
print( 'Tiempo not == es ' + str(fin-inicio-vacio) )
inicio = time.time()
i = 0
while (i<tam) :
distinto()
i = i + 1
fin = time.time()
print( 'Tiempo != es ' + str(fin-inicio-vacio) )
inicio = time.time()
i = 0
while (i<tam) :
igual_else()
i = i + 1
fin = time.time()
print( 'Tiempo == else es ' + str(fin-inicio-vacio) )
x='val'
test(10000000)
使用 python 解释器执行它时,得到的结果是:
jose2@HP-Negro:~/t$ python a.py
Tiempo not == es 1.71001195908
Tiempo != es 1.9246609211
Tiempo == else es 1.75712680817
如果我多次运行它,我会得到类似的结果。看起来赢家不是 ==。
现在我用cpython将它编译成C。我编译为我执行的 Linux 的 ELF 二进制文件的 C 代码:
jose2@HP-Negro:~/t$ gcc -O2 -I /usr/include/python3.5m -o a a.c -lpython3.5m -lpthread -lm -lutil -ldl
jose2@HP-Negro:~/t$ ./a
Tiempo not == es 0.6007065773010254
Tiempo != es 0.6298408508300781
Tiempo == else es 0.6232995986938477
jose2@HP-Negro:~/t$ ./a
Tiempo not == es 0.5901763439178467
Tiempo != es 0.6861095428466797
Tiempo == else es 0.6084094047546387
jose2@HP-Negro:~/t$ ./a
Tiempo not == es 0.6090543270111084
Tiempo != es 0.6182305812835693
Tiempo == else es 0.6077189445495605
jose2@HP-Negro:~/t$ gedit a.py
jose2@HP-Negro:~/t$ python a.py
Tiempo not == es 2.22967505455
Tiempo != es 2.49930405617
Tiempo == else es 2.18658304214
import time, array
#Las pruebas las realicé con cada una de las dos siguientes líneas:
#x,y = 'val','lav'
#x,y = 'va1','lav'
print (x,y)
t = array.array('d')
suma = 0
for j in range(0,100):
ti = time.process_time()
for i in range (0,100000):
if x == 'val': # not x == 'val' # x != 'val'
y = 'val'
tf = time.process_time()
dif = tf - ti
t.append(dif)
suma += dif
print ('Promedio = ', suma / 100)
拆解
如果我们使用Python (
dis
)的反汇编程序,我们会看到所有 3 个都编译为相同数量的指令,并且仅在POP_JUMP_IF_TRUE
oPOP_JUMP_IF_FALSE
Demo en ideone
轮廓
使用cProfile,我们可以测量执行时间并执行基准测试:
从最慢到最快排序,我们可以看到:
if not x == 'val'
这是最慢的。if x == 'val'
+else
大约快1.7% 。if x != 'val'
它甚至快3.6% 。Demo en ideone
* 或者这里有一个更复杂的例子,用随机字符串比较真假情况。
结论
条件
if x != 'val'
稍微有效一些。但是,在我看来,差异并不足以在编码时改变样式。我绝对希望代码尽可能易于阅读,并且我只会考虑在需要节省每一秒可能的时间的极其密集的计算中考虑这个结果。
三个都一样
对标并不容易
从可观察行为的角度来看,这三者都是一样的。因此,python 编译器或解释器可以在所有三种情况下生成/执行完全相同的代码。在这种情况下,它将花费完全相同的时间来执行,因为它是相同的生成代码。可观察到的差异将是噪音。
有人可能会想反汇编生成的代码,然后发现它在所有三种情况下都不同。但是以这种方式得出的结论只适用于已经完成测试的python版本。它们一般不适用。
让我们观察一下使用两种不同的方法执行这些指令我们如何获得不同的结果。让我们考虑以下程序:
使用 python 解释器执行它时,得到的结果是:
如果我多次运行它,我会得到类似的结果。看起来赢家不是 ==。
现在我用cpython将它编译成C。我编译为我执行的 Linux 的 ELF 二进制文件的 C 代码:
现在有时一个人获胜,有时另一个人获胜。
但我不仅可以在不同的执行环境下得到不同的结果。使用相同的执行环境,结果可能会因输入数据而异。让我们将行更改
x='val'
为x='xxx'
并再次使用解释器运行:现在是== else获胜。并且当多次执行时,这个结果会重复。而且我使用完全相同的系统运行它,在获胜者不是 ==之前,只有输入发生了变化。
上述基准都不是很好。在所有测试中,
x
从测试开始到结束, 的值始终相同。还需要使用随机数据进行测试,或者更好的是,使用从与我们的程序预期运行的情况类似的情况中获得的数据进行测试。我们可以发现一些惊喜,例如有序数据的处理速度比随机数据快;从而将所有价值移至上述过于简单的基准。我认为没有必要比较这些比较运算符来确定一个是否比另一个更有效,主要是因为计算完成得如此之快以至于几乎不可能检测到差异。
但是,在我看来,与其中之一进行比较时存在差异。
理论上,使用
比使用更有效
主要原因是因为!=直接进行比较并询问x是否与z不同。相反,not x == z执行两个操作而不是一个,因为它首先检查x是否等于z,然后否定该操作的结果。
另一方面,我们必须考虑进行比较的上下文,实际上,使用其中一个或另一个取决于此。我的意思是,有时使用not比使用!=阅读和解释一段代码更清晰,例如:
我发现以下代码行更具可读性:
这是什么:
而且由于我在谈论代码可读性,我建议不要使用保留字,例如pass或break,因为它们会以某种突然的方式中断代码流并使其难以阅读,从而使其复杂且难以理解。 。如此之多,以至于有些人认为它是意大利面条代码。
使用以下算法,我得到的时间差异非常小:
平均值在千分之 12 到 14 秒之间,其中
if
TRUE
; 在 9 到 13 毫秒之间,使用if
FALSE
.从最快到最慢的位置如下:
if
TRUE
if x == 'val'
if x != 'val'
if not x == 'val'
if
FALSE
if x != 'val'
if not x == 'val'
if x == 'val'
根据Python数据模型
__ne__
,如果一个类没有实现该方法,它就会委托给该方法__eq__
。因此,假设检查a == b
比检查更有效a != b
。另一方面,
if not
根据设计,检查被认为是单个原子操作,而不是因为解释器实现的怪癖(如某些评论中所建议的那样),就像not a is b
and操作被确定为等效一样a is not b
。所以正确答案应该更有效率
if not x == y
。但是对于 python 本地类型,情况并非如此,因为它们通常实现了数据模型的所有方法,此外,与用户创建的方法相比,它们的调用更加优化。我的建议是不要沉迷于性能,因为改进来自其他地方,例如要比较的变量是本地的(而不是使用全局变量)或生成与函数组合的表达式,
any()
或者all()
不是使用 some 的典型循环if
。在我看来,两者都是相同的功能,它发生在第一个:
您正在将条件语句调节为否定,也就是说,如果 X 等于 val 不正确,则执行某些操作,运行 if,否则如果 X 是 VAL 为真,则执行其他操作
在第二
你也在做同样的事情,但你说:
如果 X 与 VAL 不同,则执行其他操作 如果 X 不等于 VAL,则执行其他操作
我似乎使用 != 不同于 . 因为您没有从一开始就否定 IF 中的整个语句
此外,阅读有关 python 如何使用这两个比较器的信息,第一个将其转换为布尔值,为什么?为什么它会询问对象“是否满足逻辑条件?”
第二个会问“你等于这个值吗?”
至于你的例子:
您声明如果 X 等于 Value 做某事,使用的方法将基于您的需要。
要知道值是否等于进入系统的变量,X == val
我要给你一个答案,不是基于反汇编,也不是时间分析……
作为一名 python 程序员,这对你来说几乎是一样的,99.99% 的时间。这样的事情很少会影响脚本的速度。事实上,在这些“微优化”上浪费时间甚至是有害的,因为在算法层面可能还有其他可能的改进。
即使使用更复杂的操作(例如字符串连接),收益通常也可以忽略不计。