小编Kel*_*ndy的帖子

我们能让 1 == 2 成立吗?

Pythonint是封装实际数值的对象。我们可以修改这个值吗,例如将对象的值设置1为 2?那么这就1 == 2变成了True

python cpython python-internals

101
推荐指数
3
解决办法
8373
查看次数

为什么 a.insert(0,0) 比 a[0:0]=[0] 慢得多?

使用列表的insert函数比使用切片分配实现相同的效果要慢得多:

> python -m timeit -n 100000 -s "a=[]" "a.insert(0,0)"
100000 loops, best of 5: 19.2 usec per loop

> python -m timeit -n 100000 -s "a=[]" "a[0:0]=[0]"
100000 loops, best of 5: 6.78 usec per loop
Run Code Online (Sandbox Code Playgroud)

(请注意,这a=[]只是设置,因此a开始时为空,但后来增长到 100,000 个元素。)

起初我想可能是属性查找或函数调用开销左右,但在末尾插入表明这是可以忽略不计的:

> python -m timeit -n 100000 -s "a=[]" "a.insert(-1,0)"
100000 loops, best of 5: 79.1 nsec per loop
Run Code Online (Sandbox Code Playgroud)

为什么可能更简单的专用“插入单个元素”功能这么慢?

我也可以在 repl.it 上重现它:

from timeit import repeat

for _ in range(3):
  for …
Run Code Online (Sandbox Code Playgroud)

python performance

70
推荐指数
1
解决办法
2143
查看次数

print(*a, a.pop(0)) 如何改变?

这段代码:

a = [1, 2, 3]
print(*a, a.pop(0))
Run Code Online (Sandbox Code Playgroud)

Python 3.8 打印2 3 1(在解包之前进行pop)。
Python 3.9 打印1 2 3 1(解压后执行pop)。

是什么导致了这种变化?我在变更日志中没有找到它。

编辑:不仅在函数调用中,而且在列表显示中:

a = [1, 2, 3]
b = [*a, a.pop(0)]
print(b)
Run Code Online (Sandbox Code Playgroud)

打印[2, 3, 1]vs[1, 2, 3, 1]打印 表达式列表显示“表达式从左到右求值”(这是 Python 3.8 文档的链接),所以我希望首先发生解包表达式。

python

64
推荐指数
1
解决办法
1701
查看次数

为什么更简单的循环速度更慢?

调用 with n = 10**8,对我来说,简单循环始终比复杂循环慢得多,我不明白为什么:

def simple(n):
    while n:
        n -= 1

def complex(n):
    while True:
        if not n:
            break
        n -= 1
Run Code Online (Sandbox Code Playgroud)

有时以秒为单位:

def simple(n):
    while n:
        n -= 1

def complex(n):
    while True:
        if not n:
            break
        n -= 1
Run Code Online (Sandbox Code Playgroud)

这是字节码的循环部分,如下所示dis.dis(simple)

  6     >>    6 LOAD_FAST                0 (n)
              8 LOAD_CONST               1 (1)
             10 BINARY_OP               23 (-=)
             14 STORE_FAST               0 (n)

  5          16 LOAD_FAST                0 (n)
             18 POP_JUMP_BACKWARD_IF_TRUE     7 (to 6)
Run Code Online (Sandbox Code Playgroud)

对于complex

 10     >>    4 …
Run Code Online (Sandbox Code Playgroud)

python performance cpython python-internals python-3.11

62
推荐指数
1
解决办法
9685
查看次数

为什么对于 bytearray 来说 b.pop(0) 比 del b[0] 慢 200 多倍?

让他们竞争 3 次(每次 100 万次弹出/删除):

\n
from timeit import timeit\n\nfor _ in range(3):\n    t1 = timeit(\'b.pop(0)\', \'b = bytearray(1000000)\')\n    t2 = timeit(\'del b[0]\', \'b = bytearray(1000000)\')\n    print(t1 / t2)\n
Run Code Online (Sandbox Code Playgroud)\n

时间比例(在线尝试!):

\n
274.6037053753368\n219.38099365582403\n252.08691226683823\n
Run Code Online (Sandbox Code Playgroud)\n

为什么pop做同样的事情要慢得多?

\n

python arrays performance cpython python-internals

57
推荐指数
2
解决办法
6156
查看次数

为什么 a=[0] 的 list(x for x in a) 比 a=[] 快?

list(x for x in a)用三个不同的 CPython 版本进行了测试。Ona = [0]比 on 快得多a = []

 3.9.0 64-bit       3.9.0 32-bit       3.7.8 64-bit
a = []  a = [0]    a = []  a = [0]    a = []  a = [0]

465 ns  412 ns     543 ns  515 ns     513 ns  457 ns   
450 ns  406 ns     544 ns  515 ns     506 ns  491 ns   
456 ns  408 ns     551 ns  513 ns     515 ns  487 ns   
455 …
Run Code Online (Sandbox Code Playgroud)

python performance cpython python-internals

36
推荐指数
1
解决办法
822
查看次数

列表的这种“贪婪”+= 行为是否得到保证?

我偶尔会使用“技巧”来通过自身的映射版本来扩展列表,例如有效地计算 2 的幂:

from operator import mul

powers = [1]
powers += map(mul, [2] * 10, powers)

print(powers)   # prints [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
Run Code Online (Sandbox Code Playgroud)

这依赖于+=立即将每个值附加map到列表中,以便map随后找到它并继续该过程。换句话说,它需要像这样工作:

powers = [1]
for value in map(mul, [2] * 10, powers):
    powers.append(value)
Run Code Online (Sandbox Code Playgroud)

而不是首先像这样计算和存储整个右侧,最终powers结果是[1, 2]

powers = [1]
powers += list(map(mul, [2] * 10, powers))
Run Code Online (Sandbox Code Playgroud)

是否在某个地方保证它能像以前那样工作?我检查了可变序列类型s += t文档,但除了暗示和的等价性之外,它没有说太多s.extend(t)。它确实引用了MutableSequence,其源代码包括:

    def extend(self, …
Run Code Online (Sandbox Code Playgroud)

python list language-lawyer

15
推荐指数
1
解决办法
477
查看次数

为什么 reversed(mylist) 这么慢?

更新:可能只发生在 Windows 的 CPython 3.8 32 位中,所以如果您不能在其他版本中重现它,请不要感到惊讶。请参阅更新部分中的表格。)

双方iterreversed因此在列表专门迭代器:

>>> iter([1, 2, 3])
<list_iterator object at 0x031495C8>

>>> reversed([1, 2, 3])
<list_reverseiterator object at 0x03168310>
Run Code Online (Sandbox Code Playgroud)

reversed一个要慢得多:

> python -m timeit -s "a = list(range(1000))" "list(iter(a))"
50000 loops, best of 5: 5.76 usec per loop

> python -m timeit -s "a = list(range(1000))" "list(reversed(a))"
20000 loops, best of 5: 14.2 usec per loop
Run Code Online (Sandbox Code Playgroud)

而且我可以始终如一地重现它。后来又试了iter五次,分别是5.98、5.84、5.85、5.87、5.86。然后又是reversed五次,分别是 14.3、14.4、14.4、14.5、14.3。

我认为iter增加列表元素的内存位置可能会带来好处,所以我事先尝试反转列表。同一张图:

> python …
Run Code Online (Sandbox Code Playgroud)

python performance 64-bit 32-bit

12
推荐指数
1
解决办法
486
查看次数

为什么 Python 的 Numpy zeros 和空函数之间的速度差异对于更大的数组大小消失了?

我被一个感兴趣的博客文章由Mike槎他比较需要两个函数的时间numpy.zeros((N,N))numpy.empty((N,N))N=200N=1000。我使用%timeit魔法在 jupyter notebook 中运行了一个小循环。下面的图表给出的所需要的时间之比numpy.zeronumpy.empty。对于N=346,numpy.zero比 慢大约 125 倍numpy.empty。在N=361及以上,这两个功能所需的时间几乎相同。

后来,在 Twitter 上的讨论导致了这样的假设:要么numpy为小分配做一些特殊的事情以避免malloc调用,要么操作系统可能会主动将分配的内存页面清零。

造成这种差异的原因是什么N,而较大的所需时间几乎相等N

在此处输入图片说明

通过启动堆溢出编辑:我可以重现它(这就是为什么我来到这里的第1名),这里有一个情节np.zerosnp.empty独立。该比率看起来像 GertVdE 的原始图:

在此处输入图片说明

在 Python 3.9.0 64 位、NumPy 1.19.2、Windows 10 Pro 2004 64 位上完成,使用此脚本生成数据:

from timeit import repeat
import numpy as np

funcs = np.zeros, np.empty

number = 10
index = …
Run Code Online (Sandbox Code Playgroud)

python performance numpy

11
推荐指数
2
解决办法
667
查看次数

为什么二分搜索优化要慢得多?

假设的优化使代码速度慢了一倍以上。

\n

我通过查找某个值出现的范围来计算该值x在排序列表中出现的频率:a

\n
from bisect import bisect_left, bisect_right\n\ndef count(a, x):\n    start = bisect_left(a, x)\n    stop = bisect_right(a, x)\n    return stop - start\n
Run Code Online (Sandbox Code Playgroud)\n

但是,嘿,它不能在开始之前停止,因此我们可以通过省略开始之前的部分(doc)来优化第二次搜索:

\n
def count(a, x):\n    start = bisect_left(a, x)\n    stop = bisect_right(a, x, start)\n    return stop - start\n
Run Code Online (Sandbox Code Playgroud)\n

但当我进行基准测试时,优化版本花费的时间是原来的两倍

\n
 254 ms \xc2\xb1  1 ms  original\n 525 ms \xc2\xb1  2 ms  optimized\n
Run Code Online (Sandbox Code Playgroud)\n

为什么?

\n

该基准测试构建了一个从 0 到 99999 的一千万个随机整数的排序列表,然后对所有不同的整数进行计数(仅用于基准测试,指出没有用Counter)(在线尝试!):

\n
import random\nfrom bisect …
Run Code Online (Sandbox Code Playgroud)

python sorting performance binary-search

8
推荐指数
1
解决办法
264
查看次数