看看这个:
>>> 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.
当通过解包参数调用函数时,它似乎会增加两次递归深度.我想知道为什么会这样.
一般:
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) 我一直在努力学习如何在幕后实现CPython.Python很高级很棒,但我不喜欢把它当成黑盒子.
考虑到这一点,元组是如何实现的?我已经看过了源码(tupleobject.c),但它已经过了我的脑海.
我看到的PyTuple_MAXSAVESIZE = 20和PyTuple_MAXFREELIST = 2000,什么是节约型和"自由列表"?(长度为20/21或2000/2001的元组之间是否存在性能差异?什么强制实现最大元组长度?)
我正在考虑将我的代码(大约30K LOC)从CPython移动到Jython,这样我就可以更好地与我的java代码集成.
是否有我应该查看的清单或指南,以帮助我进行迁移?做有类似事情的人有经验吗?
从阅读Jython网站开始,大多数问题都显得过于模糊,无法打扰我.
我注意到:
还要别的吗?
解释我的问题的最好方法是举个例子:
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) CPython的deque被实现为64项的双向链表大小的"块"(阵列).除了链表两端的那些块外,这些块都是满的.在IIUC中,当pop/ popleft删除块中的最后一项时,块被释放; 当append/ appendleft尝试添加新项目并且相关块已满时,将分配它们.
我理解使用链接列表而不是链接项列表所列出的优点:
malloc/ free添加/删除的每个项目执行/的运行时成本但是为什么不是首先使用单个动态大小的圆形数组而不是双链表呢?
AFAICT,圆形阵列将保留所有上述优点,并维持(atortized)成本pop*/ append*at O(1)(通过分配,就像在中list).此外,它还可以提高从当前O(n)到索引的索引查找成本O(1).循环数组也可以更简单地实现,因为它可以重用大部分list实现.
我可以在C++这样的语言中看到支持链表的论证,其中可以O(1)使用指针或迭代器从中间删除项目; 但是,python deque没有API来执行此操作.
如何在python中加载ac#dll?
我是否必须在c#文件中添加一些额外的代码?(比如在c ++文件中导出)
我不想使用IronPython.我想将模块导入Python!
我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) 请参阅此链接:https : //docs.python.org/3/c-api/long.html#c.PyLong_FromLong
当前的实现为 -5 到 256 之间的所有整数保留了一个整数对象数组;当您在该范围内创建一个 int 时,您实际上只是取回了对现有对象的引用。所以,应该可以改变 1 的值。我怀疑 Python 的行为,在这种情况下,是 undefined。:-)
在这种情况下,粗线是什么意思?
该描述对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真的含有"局部变量的名字"?
如评论/答案中所述,这似乎是文档错误.Bug问题在这里提交.
拉请求修复此文档错误已批准并等待合并.
cpython ×10
python ×10
python-3.x ×2
.net ×1
bytecode ×1
c# ×1
integer ×1
jython ×1
migration ×1
python-2.7 ×1
python.net ×1
recursion ×1
scope ×1
tuples ×1