标签: python-internals

如何交换python元组中的成员(a,b)=(b,a)在内部工作?

In [55]: a = 5

In [56]: b = 6

In [57]: (a, b) = (b, a)

In [58]: a
Out[58]: 6

In [59]: b
Out[59]: 5
Run Code Online (Sandbox Code Playgroud)

如何交换a和b的值在内部工作?它肯定不使用临时变量.

python tuples python-internals iterable-unpacking

27
推荐指数
1
解决办法
1万
查看次数

为什么CPython中的id({})== id({})和id([])== id([])?

为什么CPython(没有关于其他Python实现的线索)有以下行为?

tuple1 = ()
tuple2 = ()                                                                                                   
dict1 = {}
dict2 = {}
list1 = []
list2 = []
# makes sense, tuples are immutable
assert(id(tuple1) == id(tuple2))
# also makes sense dicts are mutable
assert(id(dict1) != id(dict2))
# lists are mutable too
assert(id(list1) != id(list2))
assert(id(()) == id(()))
# why no assertion error on this?
assert(id({}) == id({}))
# or this?
assert(id([]) == id([]))
Run Code Online (Sandbox Code Playgroud)

我有一些想法可能,但找不到具体原因.

编辑

进一步证明格伦和托马斯的观点:

[1] id([])
4330909912
[2] x = []
[3] …
Run Code Online (Sandbox Code Playgroud)

python identity cpython python-internals

26
推荐指数
2
解决办法
1787
查看次数

为什么Python处理'1是1**2'与'1000是10**3'不同?

这个关于缓存小整数和字符串的问题的启发,我发现了以下我不理解的行为.

>>> 1000 is 10**3
False
Run Code Online (Sandbox Code Playgroud)

我以为我理解了这种行为:1000是很大的缓存.1000和10**3指向2个不同的对象.但我错了:

>>> 1000 is 1000
True
Run Code Online (Sandbox Code Playgroud)

因此,Python可能会将计算与"正常"整数区别对待.但这种假设也是不正确的:

>>> 1 is 1**2
True
Run Code Online (Sandbox Code Playgroud)

如何解释这种行为?

python reference python-internals semantics

26
推荐指数
1
解决办法
1519
查看次数

参数解包浪费堆栈帧

当通过解包参数调用函数时,它似乎会增加两次递归深度.我想知道为什么会这样.

一般:

depth = 0

def f():
    global depth
    depth += 1
    f()

try:
    f()
except RuntimeError:
    print(depth)

#>>> 999
Run Code Online (Sandbox Code Playgroud)

通过拆包电话:

depth = 0

def f():
    global depth
    depth += 1
    f(*())

try:
    f()
except RuntimeError:
    print(depth)

#>>> 500
Run Code Online (Sandbox Code Playgroud)

理论上两者都应达到1000左右:

import sys
sys.getrecursionlimit()
#>>> 1000
Run Code Online (Sandbox Code Playgroud)

这发生在CPython 2.7和CPython 3.3上.

在PyPy 2.7和PyPy 3.3上存在差异,但它要小得多(1480 vs 1395和1526 vs 1395).


从反汇编中可以看出,除了调用类型(CALL_FUNCTIONvs CALL_FUNCTION_VAR)之外,两者之间几乎没有区别:

import dis
Run Code Online (Sandbox Code Playgroud)
def f():
    f()

dis.dis(f)
#>>>  34           0 LOAD_GLOBAL              0 (f)
#>>>               3 CALL_FUNCTION            0 (0 positional, …
Run Code Online (Sandbox Code Playgroud)

python recursion cpython python-internals

26
推荐指数
1
解决办法
665
查看次数

有没有比dict()更快的东西?

我需要一种更快的方式来存储和访问大约3GB的k:v对.其中kstringinteger并且v是一个np.array(),可以是不同的形状.有没有任何对象,比标准python dict在存储和访问这样的表时更快?例如,a pandas.DataFrame

到目前为止,我已经了解python dict是一个相当快速的哈希表实现,有什么比我的具体案例更好的?

python dictionary numpy python-3.x python-internals

26
推荐指数
3
解决办法
2万
查看次数

Python的引用传递

您好我正在尝试理解Python的引用如何通过工作.我有一个例子:

>>>a = 1
>>>b = 1
>>>id(a);id(b)
140522779858088
140522779858088
Run Code Online (Sandbox Code Playgroud)

这非常有意义,因为a和b都引用了与身份相同的值.我不太明白的是这个例子:

>>>a = 4.4
>>>b = 1.0+3.4
>>>id(a);id(b)
140522778796184
140522778796136
Run Code Online (Sandbox Code Playgroud)

与此示例不同:

>>>a = 2
>>>b = 2 + 0
>>>id(a);id(b)
140522779858064
140522779858064
Run Code Online (Sandbox Code Playgroud)

是因为在第3个例子中,0 int对象被解释器视为"None",并且没有被识别为需要与变量"a"引用的对象不同的身份(2)?而在第二个例子中,"b"是添加两个不同的int对象,而解释器是为要添加的两个对象分配内存,这给变量"a",与变量"b"不同的标识?

python literals python-internals

26
推荐指数
2
解决办法
2416
查看次数

将一系列int转换为字符串 - 为什么应用比astype快得多?

我有一个pandas.Series包含整数,但我需要将这些转换为字符串以用于某些下游工具.所以假设我有一个Series对象:

import numpy as np
import pandas as pd

x = pd.Series(np.random.randint(0, 100, 1000000))
Run Code Online (Sandbox Code Playgroud)

在StackOverflow和其他网站上,我见过大多数人认为最好的方法是:

%% timeit
x = x.astype(str)
Run Code Online (Sandbox Code Playgroud)

这大约需要2秒钟.

使用时x = x.apply(str),只需0.2秒.

为什么x.astype(str)这么慢?应该推荐的方式x.apply(str)吗?

我主要对python 3的行为感兴趣.

python string performance python-internals pandas

26
推荐指数
2
解决办法
1490
查看次数

何时是标准库模块中的函数,称为内置函数?

我对"内置"功能一词感到困惑.我认为这只意味着内置于解释器中的那些函数并记录在其中 - 2.内置函数
但似乎标准库模块中定义的函数也是内置函数(在某些情况下).例如 -

>>> import os
>>> os.chdir
<built-in function chdir>
>>> import warnings
>>> warnings.warn
<built-in function warn>
>>> import json
>>> json.dumps
<function dumps at 0x7f3643a240d0> # not built-in
>>> dir
<built-in function dir>
>>> 
Run Code Online (Sandbox Code Playgroud)

那么什么时候标准库模块中的函数称为内置函数,何时不是?

python python-3.x python-internals

26
推荐指数
3
解决办法
1594
查看次数

有效地按Python 3.6+中的位置访问字典项

我理解字典是在Python 3.6+中排序插入,作为3.6中的实现细节和3.7+中的官方.

鉴于它们是有序的,似乎很奇怪,没有方法可以通过插入顺序检索字典的i项.该唯一的解决方案可出现有O(ñ)的复杂性,无论是:

  1. 通过O(n)进程转换为列表然后使用list.__getitem__.
  2. enumerate循环中的字典项,并在达到所需索引时返回值.同样,O(n)时间复杂度.

由于从list具有O(1)复杂度的项目中获取项目,是否有办法通过字典实现相同的复杂性?无论是定期dict还是collections.OrderedDict工作.

如果不可能,是否存在阻止这种方法的结构性原因,或者这只是一个尚未考虑/实施的特征?

python dictionary python-3.x python-internals

26
推荐指数
1
解决办法
2567
查看次数

使对象x使得"x in [x]"返回False

如果我们制作这样的病态土豆:

>>> class Potato:
...     def __eq__(self, other):
...         return False
...     def __hash__(self):
...         return random.randint(1, 10000)
... 
>>> p = Potato()
>>> p == p
False
Run Code Online (Sandbox Code Playgroud)

我们可以通过这种方式打破集合和切换(注意:即使__eq__返回True它也是一样的,它正在破坏它们的哈希):

>>> p in {p}
False
>>> p in {p: 0}
False
Run Code Online (Sandbox Code Playgroud)

此外len({p: 0, p: 0}) == 2,并{p: 0}[p]引发KeyError,基本上所有与映射相关的东西都会出现,如预期的那样.

但我没想到的是我们不能打破名单

>>> p in [p]
True
Run Code Online (Sandbox Code Playgroud)

这是为什么?它似乎是list.__contains__迭代,但它首先在检查相等之前检查身份.由于不是身份意味着相等的情况(例如参见NaN对象),列表在身份比较中短路的原因是什么?

python python-internals

25
推荐指数
2
解决办法
1140
查看次数