如何在Python中动态分配内存

9
有没有在Python中获取堆内存块并使用变量引用它的方法,就像其他语言中的关键字“new”或函数malloc()一样?
Object *obj = (Object *) malloc(sizeof(Object)); 
Object *obj = new Object();

在这个项目中,我的程序在不确定的时间间隔内等待接收一些数据,并且当正确时,数据的长度是固定的字节数。
我通常这样使用它:
void receive()// callback
{
  if(getSize()<=sizeof(DataStruct))
  {
   DataStruct *pData=malloc(sizeof(DataStruct));
   if(recvData(pData)>0)
   list_add(globalList,pData);
  }   
}

void worker()
{
  init()
  while(!isFinish)
 {
  dataProcess(globalList);
 }

}

现在我想把这些旧项目迁移到Python上,并尝试以如下方式进行:

def reveive():
 data=dataRecv()
 globalList.append(data)

然而,我发现列表中的所有项目都相同,并且等于最新接收到的项目。很明显,所有列表项都指向同一个内存地址,我希望每次调用函数时都能获得一个新的内存地址。

在Python中,globalList是什么?是局部变量吗? - Boiethios
4
你没有用正确的方式尝试解决问题。Python是一种高级语言,你根本不需要分配内存。如果你展示dataRecv的定义(或者调用的任何内容 - 最小可复现代码),那么实际问题可能会更清晰。我猜测你正在清空和重用单个列表对象,而不是创建一个新的列表对象。可能你遇到了可怕的可变默认参数问题。 - jonrsharpe
谢谢,dataRecv是从另一个导入模块中获取的,并且我省略了用于调用dataRecv的参数。我在receive()函数中打印了data,这是正确的。正如你所说,我并没有创建一个新的列表对象。这正是我所询问的,我需要一种方法来实现C++中的关键字"new"。 - lb lb
3个回答

8

在Python中,“new”的等效方法是使用构造函数,例如:

new_list = list() # or [] - expandable heterogeneous list
new_dict = dict() # expandable hash table
new_obj = CustomObject() # assuming CustomObject has been defined

由于您正在从C语言移植,因此需要注意一些事项。在Python中,所有东西都是对象,包括整数,大多数变量只是引用,但标量变量(如整数和字符串)与容器的规则不同,例如:

a = 2   # a is a reference to 2
b = a   # b is a reference to 'a'
b = 3   # b now points to 3, while 'a' continues to point to 2

然而:
alist = ['eggs', 2, 'juice']  # alist is reference to a new list
blist = alist # blist is a reference; changing blist affects alist
blist.append('coffee') # alist and blist both point to 
                       # ['eggs', 2, 'juice', 'coffee']

如果你愿意,你可以预先分配大小,但在Python中这通常不会带来太多好处。下面的写法是合法的:

new_list4k = [None]*4096 # initialize to list of 4096 None's 
new_list4k = [0]*4096    # initialize to 4096 0's
big_list = []
big_list.extend(new_list4k) # resizes big_list to accomodate at least 4k items

如果您想确保不会发生内存泄漏,请尽可能经常使用局部变量,例如,在函数内部使用,因此当事物超出范围时,您不必担心。

为了进行高效的矢量化操作(并且具有更低的内存占用),请使用numpy数组。

import numpy as np
my_array = np.zeros(8192) # create a fixed array length of 8K elements
my_array += 4             # fills everything with 4

我想先问一下你的主要目标是什么。有些方法是符合Python编程规范的,可以尝试优化程序执行速度或者使用最少的内存空间。但如果你想在最短的时间内移植程序,可能需要考虑其他方案。有时候这些方案会相互交叉,但通常来说,符合Python编程规范的方法翻译起来会更快,但需要更多的内存。如果想要让Python性能更好,可能需要更专注的经验。祝你好运!


非常感谢,我已经解决了。 - lb lb

3

您应该阅读Python教程

您可以在Python中创建列表、字典、对象和闭包。所有这些都存在于(Python)中,而Python具有天真的垃圾回收器(引用计数+循环标记)。

(Python GC是天真的,因为它不使用复杂的GC技术;因此它比例如Ocaml或许多JVM分代复制垃圾回收器慢;阅读GC手册获取更多信息;但是Python GC对外部C代码更加友好)


天真?就是指轻信、天真无邪,容易被欺骗的意思吗?缺乏世故经验?有点带有偏见,对吗? - rici

1
请记住,解释性语言通常不会像编译语言那样将类型展开。内存布局(可能)与原始数据完全不同。因此,您不能简单地将原始数据强制转换为类实例或反之亦然。您必须手动读取原始数据,解释并填充对象。

从技术上讲,Python是编译型语言。解释型语言是逐个字符运行的,而编译型语言则被转换为字节码,然后由相应的虚拟机运行。 - nerdguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接