__sizeof__在不同的Python对象上尝试使用魔术方法(特别是)我偶然发现了以下行为:
Python 2.7
>>> False.__sizeof__()
24
>>> True.__sizeof__()
24
Run Code Online (Sandbox Code Playgroud)
Python 3.x
>>> False.__sizeof__()
24
>>> True.__sizeof__()
28
Run Code Online (Sandbox Code Playgroud)
Python 3中改变了什么使得大小True超过了False?
一个相当常见的操作是list基于另一个过滤一个list.人们很快发现这个:
[x for x in list_1 if x in list_2]
Run Code Online (Sandbox Code Playgroud)
大输入速度慢 - 它是O(n*m).呸.我们如何加快速度?使用a set进行过滤查找O(1):
s = set(list_2)
[x for x in list_1 if x in s]
Run Code Online (Sandbox Code Playgroud)
这给出了很好的整体O(n)行为.然而,我经常看到即使是经验丰富的编码员也会陷入The Trap ™:
[x for x in list_1 if x in set(list_2)]
Run Code Online (Sandbox Code Playgroud)
确认!这也是O(n*m),因为python set(list_2) 每次构建,而不仅仅是一次.
我认为那是故事的结尾 - python无法优化它只能构建set一次.请注意陷阱.要忍受它.嗯.
#python 3.3.2+
list_2 = list(range(20)) #small for demonstration purposes
s = set(list_2)
list_1 = list(range(100000))
def f():
return [x for x in list_1 if x in s] …Run Code Online (Sandbox Code Playgroud) 调用 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) 我想知道为什么一个类__dict__是一个类mappingproxy,但实例__dict__只是一个简单的例子dict
>>> class A:
... pass
>>> a = A()
>>> type(a.__dict__)
<class 'dict'>
>>> type(A.__dict__)
<class 'mappingproxy'>
Run Code Online (Sandbox Code Playgroud) 让他们竞争 3 次(每次 100 万次弹出/删除):
\nfrom 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)\nRun Code Online (Sandbox Code Playgroud)\n时间比例(在线尝试!):
\n274.6037053753368\n219.38099365582403\n252.08691226683823\nRun Code Online (Sandbox Code Playgroud)\n为什么pop做同样的事情要慢得多?
为什么set函数调用会消除欺骗,但解析集合文字却没有?
>>> x = Decimal('0')
>>> y = complex(0,0)
>>> set([0, x, y])
{0}
>>> {0, x, y}
{Decimal('0'), 0j}
Run Code Online (Sandbox Code Playgroud)
(Python 2.7.12.可能与此类似问题的根本原因相同)
令人惊讶的是,我发现startswith速度比in:
In [10]: s="ABCD"*10
In [11]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 307 ns per loop
In [12]: %timeit "XYZ" in s
10000000 loops, best of 3: 81.7 ns per loop
Run Code Online (Sandbox Code Playgroud)
众所周知,in操作需要搜索整个字符串,startswith只需要检查前几个字符,所以startswith应该更有效率.
什么时候s足够大,startswith速度更快:
In [13]: s="ABCD"*200
In [14]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 306 ns per loop
In [15]: %timeit "XYZ" in s
1000000 loops, best of 3: 666 ns per loop
Run Code Online (Sandbox Code Playgroud)
所以看起来调用 …
我想知道在命令上执行的代码究竟是什么:
>>> from __future__ import braces
SyntaxError: not a chance
Run Code Online (Sandbox Code Playgroud)
所以,因为python是开源的,我打开C:\Python27\Lib\__future__.py并查看.令人惊讶的是,我发现没有处理导入braces模块的东西.
所以,我的问题是,处理这个问题的代码在哪里?当我运行该命令时会发生什么?
为什么使用不同值初始化的范围在Python 3中相互比较?
当我在我的解释器中执行以下命令时:
>>> r1 = range(0)
>>> r2 = range(2, 2, 2)
>>> r1 == r2
True
Run Code Online (Sandbox Code Playgroud)
结果是True.为什么会这样?为什么range具有不同参数值的两个不同对象被视为相等?
python ×10
python-internals ×10
python-3.x ×5
cpython ×4
python-2.7 ×3
performance ×2
arrays ×1
class ×1
hash ×1
identity ×1
python-2.x ×1
python-3.11 ×1
range ×1
set ×1
startswith ×1