为什么Python语句'如果东西是None'比'如果不是东西'要快得多?
编写斐波那契函数时遇到了这个问题。为了使它更快,我使用名为cache的字典来存储已经计算的数字。所以我写了为什么Python语句'如果东西是None'比'如果不是东西'要快得多?
def fib(n, cache=None):
if not cache:
cache = {}
if n in cache:
return cache[n]
if n==0 or n==1:
return 1
else:
cache[n] = fib(n-1, cache) + fib(n-2, cache)
return cache[n]
def fib_run(n):
start = time.time()
fib(n)
end = time.time()
print("fib_run cost: {}".format(end-start))
我呼吁fib_run(30)
,输出为fib_run cost: 0.8419640064239502
,它只是作为不带缓存的功能缓慢。 但是,当我在功能fib2
中将if not cache:
更改为if cache is None:
时,它的工作速度更快。
def fib2(n, cache=None):
if cache is None:
cache = {}
if n in cache:
return cache[n]
if n==0 or n==1:
return 1
else:
cache[n] = fib2(n-1, cache) + fib2(n-2, cache)
return cache[n]
def fib2_run(n):
start = time.time()
fib2(n)
end = time.time()
print("fib_run cost: {}".format(end-start))
>>> fib2_run(30)
fib2_run cost: 2.6226043701171875e-05
我想知道为什么两种方法之间存在如此巨大的差异(我认为它们在早期是一样的)。谢谢。
这里的问题不是is None
VS not cache
的表现,相反,它是if cache is None
是True
仅仅在fib2
而if not cache
是True
即使cache == {}
为fib
第一次调用。 “空”的集合评估为因此False
not
一个空的集合会True
:
>>> not {}
True
所以你在做额外的工作(以{}
分配缓存),即使在情况下,cache
已经等于{}
。
一般来说,这些操作在性能上非常相似,一个是简单的身份检查,而另一个是基于值的单数(对于字典而言,基于__len__
的结果,如果我不是错误)。
这有助于很多,谢谢。 –
@KasheemLew不客气,很高兴我能帮到你! :-) –
在第一种情况下,缓存总是空的!难怪你获得与没有缓存的功能相同的时间。所有你需要的是打印看看会发生什么。
if not cache:
#if cache is None:
print(n, "No cache!")
cache = {}
如上所述,空集合评估为false。在递归调用中,if not cache
总是如此,你创建一个新的字典,你发送一个级别在下面,这又被评估为错误的,等等。缓存中永远不会有单个条目。
(做额外的工作,甚至在缓存中已经等于{}的情况下,如上面提到的,是一个时间的操作。不应该花费更大的ñ东西)
'缓存None'是身份检查。 'not cache'是字典的空白检查。这些是引擎盖下的两种不同的操作。 –
你的意思是空虚检查花费更多的时间?你能告诉我为什么吗? –