标签: cpython

为什么这两个功能不同?

看看这个:

>>> def f():
...     return (2+3)*4
... 
>>> dis(f)
  2           0 LOAD_CONST               5 (20)
              3 RETURN_VALUE  
Run Code Online (Sandbox Code Playgroud)

显然,编译器已预先评估(2+3)*4,这是有道理的.

现在,如果我只是改变操作数的顺序*:

>>> def f():
...     return 4*(2+3)
... 
>>> dis(f)
  2           0 LOAD_CONST               1 (4)
              3 LOAD_CONST               4 (5)
              6 BINARY_MULTIPLY     
              7 RETURN_VALUE  
Run Code Online (Sandbox Code Playgroud)

表达式不再完全预先评估!这是什么原因?我正在使用CPython 2.7.3.

python bytecode cpython python-2.7

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

参数解包浪费堆栈帧

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

一般:

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
查看次数

如何在CPython中实现元组?

我一直在努力学习如何在幕后实现CPython.Python很高级很棒,但我不喜欢把它当成黑盒子.

考虑到这一点,元组是如何实现的?我已经看过了源码(tupleobject.c),但它已经过了我的脑海.

我看到的PyTuple_MAXSAVESIZE = 20PyTuple_MAXFREELIST = 2000,什么是节约型和"自由列表"?(长度为20/21或2000/2001的元组之间是否存在性能差异?什么强制实现最大元组长度?)

python tuples cpython data-structures python-internals

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

从CPython迁移到Jython

我正在考虑将我的代码(大约30K LOC)从CPython移动到Jython,这样我就可以更好地与我的java代码集成.

是否有我应该查看的清单或指南,以帮助我进行迁移?做有类似事情的人有经验吗?

从阅读Jython网站开始,大多数问题都显得过于模糊,无法打扰我.

我注意到:

  • 线程安全是一个问题
  • Unicode支持似乎完全不同,这对我来说可能是一个问题
  • mysqldb不起作用,需要用zxJDBC替换

还要别的吗?

相关问题:编写在CPython,Jython和IronPython中运行的python代码有哪些策略

python migration jython cpython

24
推荐指数
3
解决办法
4280
查看次数

嵌套列表理解范围

解释我的问题的最好方法是举个例子:

example.py:

class A(object):
    integers = [1, 2, 3]
    singles = [i for i in integers]

class B(object):
    integers = [1, 2, 3]
    pairs = [(i, j) for i in integers for j in integers]
Run Code Online (Sandbox Code Playgroud)

当我在python 2下运行它时工作正常,但在python 3下我得到一个NameErrorfor class B(但不是class A):

$ python example.py
Traceback (most recent call last):
  File "example.py", line 6, in <module>
    class B(object):
  File "example.py", line 8, in B
    pairs = [(i, j) for i in integers for j in integers]
  File …
Run Code Online (Sandbox Code Playgroud)

python scope cpython python-3.x

23
推荐指数
1
解决办法
2431
查看次数

为什么deque实现为链表而不是循环数组?

CPython的deque实现为64项的双向链表大小的"块"(阵列).除了链表两端的那些块外,这些块都是满的.在IIUC中,当pop/ popleft删除块中的最后一项时,块被释放; 当append/ appendleft尝试添加新项目并且相关块已满时,将分配它们.

我理解使用链接列表而不是链接项列表所列出的优点:

  • 减少每个项目中prev和next的指针的内存成本
  • 减少为malloc/ free添加/删除的每个项目执行/的运行时成本
  • 通过将连续指针放在彼此旁边来改善缓存局部性

但是为什么不是首先使用单个动态大小的圆形数组而不是双链表呢?

AFAICT,圆形阵列将保留所有上述优点,并维持(atortized)成本pop*/ append*at O(1)(通过分配,就像在中list).此外,它还可以提高从当前O(n)到索引的索引查找成本O(1).循环数组也可以更简单地实现,因为它可以重用大部分list实现.

我可以在C++这样的语言中看到支持链表的论证,其中可以O(1)使用指针或迭代器从中间删除项目; 但是,python deque没有API来执行此操作.

python cpython python-3.x python-internals

23
推荐指数
2
解决办法
1159
查看次数

如何在python中加载C#dll?

如何在python中加载ac#dll?

我是否必须在c#文件中添加一些额外的代码?(比如在c ++文件中导出)

我不想使用IronPython.我想将模块导入Python!

.net c# python cpython python.net

22
推荐指数
4
解决办法
5万
查看次数

当python添加小的int时,幕后会发生什么?

id最近在摆弄并意识到(c?)Python做了一些非常明智的事情:它确保小的int总是有相同的id.

>>> a, b, c, d, e = 1, 2, 3, 4, 5
>>> f, g, h, i, j = 1, 2, 3, 4, 5
>>> [id(x) == id(y) for x, y in zip([a, b, c, d, e], [f, g, h, i, j])]
[True, True, True, True, True]
Run Code Online (Sandbox Code Playgroud)

但后来我想知道数学运算的结果是否也是如此.原来它是:

>>> nines = [(x + y, 9) for x, y in enumerate(reversed(range(10)))]
>>> [id(x) == id(y) for x, y in nines]
[True, True, True, True, True, True, …
Run Code Online (Sandbox Code Playgroud)

python integer cpython

22
推荐指数
2
解决办法
849
查看次数

从 CPython 文档中澄清“应该可以更改 1 的值”

请参阅此链接:https : //docs.python.org/3/c-api/long.html#c.PyLong_FromLong

当前的实现为 -5 到 256 之间的所有整数保留了一个整数对象数组;当您在该范围内创建一个 int 时,您实际上只是取回了对现有对象的引用。所以,应该可以改变 1 的值。我怀疑 Python 的行为,在这种情况下,是 undefined。:-)

在这种情况下,粗线是什么意思?

python implementation cpython

22
推荐指数
1
解决办法
1950
查看次数

什么是co_names?

描述co_names在检查模块读取:

局部变量名称的元组

但实际上它似乎co_names是全局变量名co_varnames的元组,而是局部变量名(和参数名)的元组.例如:

a = 1

def f(b):
    c = a + b

print(f.__code__.co_varnames)  # prints ('b', 'c')
print(f.__code__.co_names)     # prints ('a',)
Run Code Online (Sandbox Code Playgroud)

此外,在dis模块的文档中,许多指令描述意味着co_names包含全局变量的名称.例如,LOAD_GLOBAL 描述如下:

将全局命名的co_names [namei]加载到堆栈中.

我在这里误解了什么吗?是否co_names真的含有"局部变量的名字"?

编辑07/17/2017

如评论/答案中所述,这似乎是文档错误.Bug问题在这里提交.

编辑07/22/2017

拉请求修复此文档错误已批准并等待合并.

python documentation cpython

20
推荐指数
1
解决办法
3016
查看次数