python列表是在堆栈内存中的函数中创建的吗?还回去安全吗?

jc3wubiy  于 2023-05-21  发布在  Python
关注(0)|答案(1)|浏览(114)

我在Python中工作。我有以下功能:

def f(list_value: list):
    a = numpy.zeros(5)
    b = numpy.zeros(4)
    list_value.append(a)
    list_value.append(b)

我使用它如下:

list_value[]
f(list_value)
a = list_value[0]
b = list_value[1]

我的问题是:使用ab安全吗?
如果用C语言编写了与此代码等效的代码,那么它将是不安全的,因为ab将是指向f函数堆栈上的内存的指针,并且使用它们将是不安全的,因为该内存的内容将更改。但我现在在Python中,我不知道Python是否提供了一些机制来防止这种情况,或者即使在Python中也是不安全的。

u5rb5r59

u5rb5r591#

Python主要是用C(cpython版本)编写的,而不是C++。numpy也有很多底层C代码。但是Python程序员通常从Python对象和引用(“指针”)的Angular 来思考,而不尝试定义底层的C或机器级等价物。一切事物都是对象,并存储在内存的“某处”。只要有一个“参考”的对象,如果percists。当引用计数下降到0时,它是垃圾收集的候选对象。因此,关键的思想是“什么创建了一个对象”,以及“什么包含了对它的引用”
区分“可变”对象(其值或属性可以更改)和“不可变”对象也很重要。
变量只包含引用。变量的标识由什么是引用来确定。变量是通过赋值创建的。
密码:

list_value = []
f(list_value)
a = list_value[0]
b = list_value[1]

list_value是指向“空”列表的变量。列表是一个对象类,可以“存储”对其他对象的引用。该存储可能是C指针数组。它也有“增长”的空间,所以将对象“附加”到列表中是有效的。但这些都是实施细节。我们讨论的是一个包含对象的列表,尽管在细节上,列表的数组只有指针,而实际的对象存储在内存中的其他地方(这会让那些试图获得列表的“内存占用”的人感到困惑,因为他们天真地使用了sys.getsizeof
下一行调用你的函数,传递给它一个对你刚刚创建的列表的引用。

def f(list_value: list):
    a = numpy.zeros(5)
    b = numpy.zeros(4)
    list_value.append(a)
    list_value.append(b)

函数'locally'创建2个numpy数组(也是对象)。它们被变量'a'和'b'本地引用,但是使用append,数组被“放置”在列表中。
通常函数会返回一些东西,比如return list_value。但是这里的返回值是None,而list_value仍然是可访问的,因为它只是通过引用传递的,并且是可变的。
返回时,函数局部变量消失,但数组仍然作为列表的元素“存在”。
因此可以通过各种方式访问它们。

a = list_value[0]
c, d = list_value    
new_list = list_value[:]
back_list = list_value[::-1]
print(list_value)
list_value[1][::2] = [10.0, 20.0]

list_value没有指示它们最初被分配给局部变量'a'和'b'。在这个意义上,列表中的数组是“无名的”。但是我们可以对这些数组做任何与它们的shapedtype一致的事情。

相关问题