TLDR:
您看到的时间差异是由于
逐项构建字典与构建列表的性能
元组然后将其转换为字典。不是因为一些
收益与收益的性能差异。
详情:
正如您实施并观察到的两种策略一样,returns 的一种比yeilds 的更快,但这也可能是由于您的策略不同而不是return vs yeild.
您的return 代码逐段构建字典,然后将其返回,而您的yield 策略返回您收集到列表中的元组并将其转换为字典。
如果我们比较将元组列表返回与将元组返回到列表中的时间会发生什么?我们会发现性能基本相同。
首先让我们确定最终会产生相同结果的 3 种方法(您的字典)
首先,让我们构建一些数据进行测试:
import random
## --------------------------
## Some random input data
## --------------------------
feature_dict = {
f"{'enable' if i%2 else 'disable'}_{i}": random.choice([True, False])
for i in range(1000)
}
## --------------------------
接下来,我们的三种测试方法。
## --------------------------
## Your "return" strategy
## --------------------------
def reverse_disable_to_enable_return(dic):
new_dic = {}
for key, val in dic.items():
if "enabl" in key:
new_dic[key] = val
if "disabl" in key:
modified_key = key.replace("disable", "enable")
if val == False:
new_dic[modified_key] = True
elif val == True:
new_dic[modified_key] = False
return new_dic
## --------------------------
## --------------------------
## Your "yield" strategy (requires cast to dict for compatibility with return)
## --------------------------
def reverse_disable_to_enable_yield(dic):
for key, val in dic.items():
if "enabl" in key:
yield key, val
if "disabl" in key:
modified_key = key.replace("disable", "enable")
if val == False:
yield modified_key, True
elif val == True:
yield modified_key, False
## --------------------------
## --------------------------
## Your "return" strategy modified to return a list to match the yield
## --------------------------
def reverse_disable_to_enable_return_apples(dic):
new_list = []
for key, val in dic.items():
if "enabl" in key:
new_list.append((key, val))
if "disabl" in key:
modified_key = key.replace("disable", "enable")
if val == False:
new_list.append((modified_key, True))
elif val == True:
new_list.append((modified_key, False))
return new_list
## --------------------------
现在,让我们从结果的角度验证它们是否基本相同:
## --------------------------
## Do these produce the same result?
## --------------------------
a = reverse_disable_to_enable_return(feature_dict)
b = dict(reverse_disable_to_enable_return_apples(feature_dict))
c = dict(reverse_disable_to_enable_yield(feature_dict))
print(a == feature_dict)
print(a == b)
print(a == c)
## --------------------------
正如我们所希望的,这告诉我们:
False
True
True
现在,时间呢?
让我们建立基本设置上下文:
import timeit
setup = '''
import random
feature_dict = {
f"{'enable' if i%2 else 'disable'}_{i}": random.choice([True, False])
for i in range(1000)
}
def reverse_disable_to_enable_return(dic):
new_dic = {}
for key, val in dic.items():
if "enabl" in key:
new_dic[key] = val
if "disabl" in key:
modified_key = key.replace("disable", "enable")
if val == False:
new_dic[modified_key] = True
elif val == True:
new_dic[modified_key] = False
return new_dic
def reverse_disable_to_enable_return_apples(dic):
new_list = []
for key, val in dic.items():
if "enabl" in key:
new_list.append((key, val))
if "disabl" in key:
modified_key = key.replace("disable", "enable")
if val == False:
new_list.append((modified_key, True))
elif val == True:
new_list.append((modified_key, False))
return new_list
def reverse_disable_to_enable_yield(dic):
for key, val in dic.items():
if "enabl" in key:
yield key, val
if "disabl" in key:
modified_key = key.replace("disable", "enable")
if val == False:
yield modified_key, True
elif val == True:
yield modified_key, False
'''
现在我们准备做一些时间安排......
我们试试吧:
timings_a = timeit.timeit("reverse_disable_to_enable_return(feature_dict)", setup=setup, number=10_000)
print(f"reverse_disable_to_enable_return: {timings_a}")
timings_b = timeit.timeit("dict(reverse_disable_to_enable_yield(feature_dict))", setup=setup, number=10_000)
print(f"reverse_disable_to_enable_yield: {timings_b}")
在我的笔记本电脑上,这是:
reverse_disable_to_enable_return: 2.30
reverse_disable_to_enable_yield: 2.71
确认您观察到yield 显然比return 慢..
但是,请记住,这并不是真正的苹果对苹果的测试。
让我们试试我们的第三种方法
timings_c = timeit.timeit("dict(reverse_disable_to_enable_return_apples(feature_dict))", setup=setup, number=10_000)
print(f"reverse_disable_to_enable_return_apples: {timings_c}")
让我们更接近我们的收益案例:
reverse_disable_to_enable_return_apples: 2.9009995
事实上,让我们将演员阵容带到dict(),看看返回一个元组列表与生成一个元组来构建一个列表......
timings_b = timeit.timeit("list(reverse_disable_to_enable_yield(feature_dict))", setup=setup, number=10_000)
print(f"reverse_disable_to_enable_yield: {timings_b}")
timings_c = timeit.timeit("reverse_disable_to_enable_return_apples(feature_dict)", setup=setup, number=10_000)
print(f"reverse_disable_to_enable_return_apples: {timings_c}")
现在我们得到:
reverse_disable_to_enable_yield: 2.13
reverse_disable_to_enable_return_apples: 2.13
向我们展示了超过 10k 次调用构建和返回元组列表的时间与产生相同元组和构建列表的时间基本相同。正如我们所料。
总结:
您看到的时间差异是由于逐项构建字典与构建元组列表然后将其转换为字典的性能差异。不是因为收益与收益的一些性能差异。