繁体   English   中英

python如何确定参数是引用还是值?

[英]How does python decide whether a parameter is a reference or a value?

在C ++中, void somefunction(int)传递一个值,而void somefunction(int&)传递一个引用。 在Java中,基元通过值传递,而对象通过引用传递。 python是如何做出这个决定的?

编辑:因为所有内容都是通过引用传递的,为什么会这样:

def foo(num):
    num *= 2

a = 4
foo(a)

print(a)

打印'4'而不是'8'?

它通过引用传递一切。 即使指定数值,它也是对包含该值的表的引用。 这是静态和动态语言之间的区别。 类型保留值,而不是容器,变量只是对所有值存在的“值空间”的引用。 您可以假设此值空间包含所有可能的不可变对象(整数,浮点数,字符串)以及您创建的所有可变对象(列表,字符串,对象)。 当然,它们的存在只有在你涉及它们时才具体化(这意味着,如果你从未在你的程序中使用数字42,那么“价值空间”中的值42就不存在分配的空间)

这样做是因为它所引用的数字是一个不可变对象。 无论如何4都是4。

def foo(num): # here, num is referring to the immutable entity 4
    num *= 2  # num now refers to the immutable entity 8

a = 4        # a now is pointing to the immutable entity 4
foo(a)       # a is still referring to the same entity 4

print(a)     # prints what a refers to, still 4

但是,如果你这样做

def foo(l):      # here, l refers to the list it receives
    l.append(5)  # the list is appended with the number 5

a = []       # a now is pointing to a specific mutable list 
foo(a)       # a is still referring to the same specific mutable list

print(a)     # prints what a refers to, the specific mutable list which now contains [5]

这里的术语存在分歧。 在Java社区中,他们说一切都是通过值传递的:原语是按值传递的; 引用按值传递。 (如果您不相信,只需在此网站上搜索Java并通过引用传递。)请注意,“对象”不是该语言中的值; 只引用对象。

它们使用的区别在于,在Java中,当您传递引用时,调用者范围中的原始引用变量永远不会被被调用者更改(即,使其指向不同的对象),这应该可以通过参考。 只有引用所指向的对象可能会发生变异,但这是无关紧要的。

Python值的工作方式与Java中的引用完全相同。 如果我们使用相同的定义,那么我们会说Python中的所有内容都是引用,并且所有内容都是按值传递的。 当然,Python社区中的一些人使用不同的定义。

对术语的不同意见是大多数混淆的根源。

既然你提到了C ++,那么你所拥有的Python代码就等同于C ++中的类似代码:

void foo(const int *num) {
    num = new int(*num * 2);
}

const int *a = new int(4);
foo(a);

print(a);

请注意,参数是一个指针,它与Java和Python中的引用最相似。

在编辑时,这是因为整数在Python中是不可变的。 所以a不会因为运行此代码时没有更改而改变:

a = 4
num = a
num *= 2
print(a)

您没有更改num (因此a ),您正在创建一个新数字并将其分配给num。

参数实际上是按值传递的。 函数传递给变量引用的对象,而不是变量本身。 函数不能重新绑定调用者的变量。 函数不能更改不可变对象,但可以更改(请求更改)可变对象。

一切都通过参考传递。 一切都是一个对象。

这不是关于函数调用语义,而是赋值语义。 在Python中,通过重新绑定引用来完成赋值,而不是通过覆盖原始对象。 这就是为什么示例代码打印4而不是8 - 它与对象的可变性无关,更多的是* =运算符不是mutator而是乘法后跟赋值。 这里num * = 2实质上是将该函数中的' num '名称重新绑定到值为' num * 2 '的新对象。 您传入的原始值始终保持不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM