导入时间
lst = [-3, 3, 7, 0, -10, 23, -9, -8, -5, -10, 9, 3,
-2, 8, -3, 6, -1, 0, 10, -1, -6, -6, 10, -7, 3, 8,
0, 7, 1, 5, -3, -6, 4, 6, -6, -4, -3, 10, 10, -5,
-7, 0, -4, -8, 2, 9, 0, -10, -3, 3, -4, 9, -7, -8,
0, -1, 1, 7, 2, -1, 3, 0, 9, -9, 4, 7, 6, 10, 8,
-6, 3, 1, 1, 9, -8, -8, 2, 4, 10, 1, 5, -1, -1, 5,
-9, 9, -3, 3, 0, -6, 2, 5, 10, 10, 5, -6, -10, -2, -9, '字符串']
start1 = time.clock()
a = all(isinstance(item, (int, float, complex)) for item in lst)
finish1 = 时间.时钟()
print("结果: {}, 时间:{:.2}ms".format(a, (finish1 - start1) * 1000))
start2 = time.clock()
def is_numbers(可迭代):
对于可迭代的项目:
如果不是 isinstance(item, (int, float, complex)):
返回假
返回真
b = is_numbers(lst)
finish2 = 时间.时钟()
print("结果: {}, 时间:{:.2}ms".format(b, (finish2 - start2) * 1000))
结果:
>>> ====== 重启:/home/dzmitry/adasdsadasdasdsad.py ====== 结果:假,时间:0.081ms 结果:假,时间:0.042ms >>> ====== 重启:/home/dzmitry/adasdsadasdasdsad.py ====== 结果:假,时间:0.085ms 结果:假,时间:0.043ms >>>
all() 函数等效于:
全部定义(可迭代):
对于可迭代的元素:
如果不是元素:
返回假
返回真
事实证明,第一种和第二种方法是等效的,除了使用生成器表达式。为什么第一种方法慢 1.5-2 倍?
这与类型检查无关——即使您将
isinstance(item, ..)调用替换为 ,时间差异仍然存在f(item),其中f该函数什么都不做,只是简单地返回True值:(f = lambda item: True以便它扫描all()整个lst列表而不会提前退出)。此外,如果完全删除函数调用,差异仍然存在:显式 for 循环比 CPython 中的生成器更有效(结果也可能取决于平台)。
all_(),手动实现,比all() 的内置版本稍慢,后者在 C 中实现了类似的循环:也就是说,重要的是使用生成器,而不是如何
all()实现它:即使是列表生成器(listcomp 是一个列表理解)也可以比等效的 genexpr 更有效(尽管在 Jython 中恰恰相反):
虽然在 Python 3 中这些表达式之间应该没有太大区别:Why is this list comprehension is faster than equivalent generator expression?
字节码没有显示出任何特别可疑的东西:
第一个片段:从 listcomp 对象创建一个函数并用结果调用它
iter(range(1000000))。第二个片段:从 genexpr 创建一个函数并使用相同的参数调用它,另外list()用结果调用该函数。listcomp 非常简单:
靠近什么:
其中
it = iter(range(1000000)), 较早获得。genexpr 看起来像:
靠近什么:
将创建的生成器(对象)传递给内置
list()函数,该函数通过调用 实现listextend(),执行与上述代码接近的代码listcomp(it)。同样,性能上的差异不在于使用list(),而在于将生成器传递给它(list(range(1000))并且也list(iter(range(1000))可以更快)。list(i for i in range(1000))[True for _ in range(1000)]这不再令人惊讶,即使
list([True for _ in range(1000)])看起来做额外的工作也可以更快list(True for _ in range(1000))(CPython/Pypy 2/3,Ubuntu)。不要对微优化太着迷——编写最简单、最易理解的代码来解决手头的问题。在测量结果表明在您的特定情况下有必要更改代码之前,请勿更改代码。
您可以使用profile查看它。
可以看到,时间除了isinstance
98902 0.125 0.000 0.125 0.000 :0(isinstance)转到 genexpr te 生成器
98903 0.406 0.000 0.531 0.000 C:/Scripts/python/2016/4/123.py:21(<genexpr>)出去: