作业的目标是初始化一个名为rand_array的空列表,然后用 10 个唯一的随机数填充它
我按照老师的指示正常完成了作业:
import random
rand_array = []
while len(rand_array) != 10:
lmnt = random.randint(1, 15)
if lmnt not in rand_array:
rand_array.append(lmnt)
print(rand_array)
后来我将其修改为内联,以提高效率,因为我的老师不喜欢我使用内联:
import random
rand_array = []
while len(rand_array) < 10:
lmnt = random.randint(1, 15)
rand_array.append(lmnt) if lmnt not in rand_array else None
我开始怀疑这是否真的更高效,如果去掉初始化空列表的要求,是否还能让它变得更好。所以,主要的问题是:“第二个版本比第一个版本更高效吗?”以及“我能让第二个版本更高效吗?”
此外,在有人说“这只是一项小任务,没关系”之前,如果我将来使用大量内联代码,我需要知道我使用它的方式是否比非内联代码更有效。
如果我输入的内容不准确,我提前表示歉意。
从技术上讲,内联实际上效率较低。它迫使 Python 执行以下操作:
None
值True
这不仅仅是理论上的;第二种方法的 CPython 字节码(来自
dis
)正是出于这个原因而具有额外的指令。不过,这确实是一个很小的差异。更重要的是,第二种方法很难阅读。三元表达式本质上只用于一种用例:
你的用例只通过了第一个测试;它既不需要 else 语句,也不需要根据 if 的结果创建变量。因此,三元表达式是一个不太直观的选择。(实际上,我不得不读了几遍代码才弄清楚为什么它没有用
None
值填充你的列表。)if 语句更易读,也更符合 Python 风格。实际的最佳解决方案是不执行上述任何一项。而是使用
random.sample
:这有三个优点:更易读、避免重复造轮子、速度更快。你可以使用以下脚本比较执行速度:
在我的机器上,差异非常大。
也许解释器可以轻松地读取第一个而不是第二个,反之亦然,但这不是我们所谈论的效率,看看这个答案。
但是用 < 替换 != 会在大规模上产生巨大的差异,从这个意义上来说,前者更有效率。
确实,< 比 != 需要更多步骤,计算量更大,因为 != 只需要异或运算。
但在实际 CPU 中,< 的结果通常会被流水线和分支预测掩盖。您可以在这里
测试一下,尽管有时可能会得到与建议相反的结果。
另外,第二段代码生成了很多 None 值,并且滥用了内联代码。
你可以考虑使用
if lmnt not in rand_array: rand_array.append(lmnt)
for inline 。一般来说,为了内联,我们会给代码添加越来越多的复杂性