我创建了一个包含一百万个对象的列表int,然后用其负值替换每个对象。tracemalloc报告 28 MB 额外内存(每个新int对象 28 字节)。为什么?intPython 不会为新对象重用垃圾收集对象的内存吗?或者我误解了tracemalloc结果?为什么会提到这些数字,它们的真正含义是什么?
import tracemalloc\n\nxs = list(range(10**6))\ntracemalloc.start()\nfor i, x in enumerate(xs):\n xs[i] = -x\nprint(tracemalloc.get_traced_memory())\nRun Code Online (Sandbox Code Playgroud)\n输出(在线尝试!):
\n(27999860, 27999972)\nRun Code Online (Sandbox Code Playgroud)\n如果我替换xs[i] = -x为x = -x(因此新对象而不是原始对象被垃圾收集),则输出仅仅是(56, 196)(尝试一下)。我保留/丢失这两个物品中的哪一个有什么区别?
如果我循环两次,它仍然只报告(27992860, 27999972)(尝试一下)。为什么不是 56MB?第二次运行与第一次运行有何不同?
我在一个名为 的 Python 文件中有以下代码benchmark.py:
source = """
for i in range(1000):
a = len(str(i))
"""
import timeit
print(timeit.timeit(stmt=source, number=100000))
Run Code Online (Sandbox Code Playgroud)
当我尝试运行多个 python 版本时,我发现性能存在巨大差异。
C:\Users\Username\Desktop>py -3.10 benchmark.py
16.79652149998583
C:\Users\Username\Desktop>py -3.11 benchmark.py
10.92280820000451
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这段代码在 python 3.11 中运行得比以前的 Python 版本更快。我尝试反汇编字节码以了解此行为的原因,但我只能看到操作码名称的差异(CALL_FUNCTION被替换为PRECALL和CALL操作码)。
我很不确定这是否是性能变化的原因。所以我正在寻找一个参考 cpython 源代码来证明合理的答案。
python 3.11字节码:
0 0 RESUME 0
2 2 PUSH_NULL
4 LOAD_NAME 0 (range)
6 LOAD_CONST 0 (1000)
8 PRECALL 1
12 CALL 1
22 GET_ITER
>> 24 FOR_ITER 22 …Run Code Online (Sandbox Code Playgroud) 我需要在Python中操作适合64位的大数字.目前,我的代码在64位平台上运行,但是它必须在32位平台上运行的可能性很小但很明显.因此,我更愿意使用long类型来表示我的数字.我知道使用longover int类型会对性能产生影响.有多糟糕?我将对它们进行大量的除法和乘法运算,但结果也应该都适合64位.
我们如何编写Python(CPython的带)绑定到一个Java库,使得想用这个Java库可以通过只写Python代码,不担心任何Java代码中使用它的开发者?
Python允许整数乘以字符串:
>>> 'hello' * 5
'hellohellohellohellohello'
Run Code Online (Sandbox Code Playgroud)
如何在CPython中实现?
我特别感谢指向源代码的指针; Mercurial存储库是一个超出我导航能力的迷宫.
我有一个简单的例子,我想从Ironpython访问(我来自'常规/理智'python')所以我正在努力将我的C++代码导入Ironpython.通常我只是使用SWIG,包装我的代码,导入并继续我的快乐方式
但是,由于Ironpython是C#而不是C语言,这使得这个过程变得更加困难
我如何为ironpython包装这个类(我还为此示例附加了我的swig文件,但这可能没用)
#include "minimal.h"
double average(std::vector<int> v) {
return std::accumulate(v.begin(), v.end(), 0.0) / v.size();
}
std::vector<double> half(const std::vector<double>& v) {
std::vector<double> w(v);
for (unsigned int i = 0; i<w.size(); i++)
w[i] /= 2.0;
return w;
}
void halve_in_place(std::vector<double>& v) {
std::transform(v.begin(), v.end(), v.begin(),
std::bind2nd(std::divides<double>(), 2.0));
}
Run Code Online (Sandbox Code Playgroud)
用头文件
#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
double average(std::vector<int> v);
std::vector<double> half(const std::vector<double>& v);
void halve_in_place(std::vector<double>& v);
Run Code Online (Sandbox Code Playgroud)
我有一个swig i文件minimal.i,但意识到有很多问题发出一个swig.exe -c ++ -python"%(FullPath)",并且铁蟒实际上在导入时接受它.
%module transfervector
%{
#include "minimal.h"
%}
%include "std_vector.i"
// …Run Code Online (Sandbox Code Playgroud) 我很清楚,这None用来表示缺乏价值.但由于在实现过程中所有内容都必须具有潜在价值,因此我希望看到使用了什么值来表示缺少值CPython.
我理解,根据文档,这NoneObject是一个单身人士.由于我的c技能是生锈的,我最好的,业余猜测,将是None指向为Py_None对象分配的内存的指针的值; 因为它是单身,这将保证唯一性.抑或是分配到c的NULL具有的价值0x0000基础上的第二个回答这个问题?
此外,文档还指出:
请注意,PyTypeObject for None不会直接在Python/C API中公开.
我猜这意味着你找不到它通过源搜索.(我做了,不知道在哪里看,object.c天真地相信我能理解任何东西)
但我不确定我对此的看法,所以我问道.
对象的c级别值是多少?Py_NoneCPython
我发现了与此问题相关的一些模糊的问题,但没有找到任何针对CPython的干净且特定的解决方案。我认为“有效”解决方案是特定于解释器的。
首先,我认为我了解:
locals() 给出了不可修改的字典。frame.f_locals给出了locals()类似的字典,但不太容易通过hackhacking exec。或至少我没有能力做些骇人听闻的未证明的事情,例如locals()['var'] = value ; exec ""exec 能够对局部变量做一些奇怪的事情,但它并不可靠-例如,我读到某处它在Python 3中不起作用。未经测试。因此,我了解到,鉴于这些限制,向局部变量添加额外的变量永远是不安全的,因为这会破坏解释器的结构。
但是,应该可以更改已经存在的变量,不是吗?
我考虑过的事情
f,可以访问f.func_code.co_nlocals和f.func_code.co_varnames。frame.f_locals。这是通过设置跟踪器的用例sys.settrace。变量应该在某个地方,最好是可写的...但是我找不到它。即使它是一个数组(用于有效的解释器访问),或者我需要一些额外的C特定接线,我也准备提交。
如何从跟踪函数或修饰的包装函数或类似的东西实现对变量的修改?
完整的解决方案当然会受到赞赏,但即使是某些指针也会对我有很大帮助,因为我在这里遇到了很多不可写的字典:-/
我在我的C++程序中嵌入了python.
我使用PyImport_ImportModule来加载我在.py文件中编写的模块.但是如何从内存中加载它?假设我的.py文件是加密的,所以我需要先解密它并将代码提供给python来执行.
此外,如果我可以绕过/拦截或修改导入机制,那将是很好的,因此不会从文件系统加载模块,而是我自己的内存块,我该怎么做?
我正在调查Python缓冲区界面,看它是否有助于优化我的项目.我的项目处理大型二进制数据文件,这两个数据文件都占用了不可靠的内存以保留在内存中(当解压缩到Python数据结构时它们可以是多个gigs)并且需要花费太多时间来按需解压缩(20-30秒完全或迭代解压).相比之下,文件足够小(数十或数百兆)以二进制形式完全存储在内存中(或者必要时通过内存映射页面存储),并且结构化使得它们需要最少的解包来从例如C使用.
我一直在阅读有关缓冲区的一些内容,例如在PEP中,但有一些事情我不清楚使用它们以原生形式存储结构:
cpython ×10
python ×10
c++ ×2
performance ×2
python-3.x ×2
binding ×1
c ×1
ironpython ×1
java ×1
memory ×1
python-3.11 ×1
string ×1
swig ×1
tracemalloc ×1
word-wrap ×1