Python 范围内有漏洞、死代码或为什么会有这样的输出?

Python 范围内有漏洞、死代码或为什么会有这样的输出?,python,pass-by-reference,pass-by-value,Python,Pass By Reference,Pass By Value,代码 def change1(list1): list1[1] = list1[1] + 5 def change2(number): number = number + 2 def main(): numbers = [4, 8, 12] change1(numbers) variable = 15 change2(variable) i = 0 while i

代码

def change1(list1):
        list1[1] = list1[1] + 5

def change2(number):
        number = number + 2

def main():
        numbers = [4, 8, 12]
        change1(numbers)
        variable = 15
        change2(variable)
        i = 0
        while i < 3:
                print numbers[i]
                i += 1
        print variable

main()
通过参考示例传递

test2.py:按引用传递和可变数据类型-示例。表/列表不足以影响main中的局部变量,您需要引用

def change1(list1):
    list1[1] = list1[1] + 5

def change2(number):
    number = [x+2 for x in number]

def main():
    numbers = [4, 8, 12]
    change1(numbers)
    variable = [15]
    change2(variable)
    i = 0
    while i < 3:
        print numbers[i]
        i += 1
    print variable[0]

main()
def change1(列表1):
列表1[1]=列表1[1]+5
def更改2(编号):
数字=[x+2表示数字中的x]
def main():
数字=[4,8,12]
更改1(数字)
变量=[15]
变更2(可变)
i=0
而我<3:
印刷数字[i]
i+=1
打印变量[0]
main()
test3.py:通过引用传递示例,在主函数外更改可变数据类型列表/表

def change1(list1):
    list1[1] = list1[1] + 5

def change2(number):
    number[0] += 2

def main():
    numbers = [4, 8, 12]
    change1(numbers)
    variable = [15]
    change2(variable)
    i = 0
    while i < 3:
        print numbers[i]
        i += 1
    print variable[0]

main()
def change1(列表1):
列表1[1]=列表1[1]+5
def更改2(编号):
数字[0]+=2
def main():
数字=[4,8,12]
更改1(数字)
变量=[15]
变更2(可变)
i=0
而我<3:
印刷数字[i]
i+=1
打印变量[0]
main()
传递值示例

test4.py:试图找到一个带有传递值的示例,为什么它不起作用

$ cat test4.py 

# Not yet a pass-by-value example!

global variable
variable = [15]

def change1(list1):
    list1[1] = list1[1] + 5

def change2(number):
    number = [x+2 for x in number] 

def main():
    numbers = [4, 8, 12]
    change1(numbers)
    #variable = 15
    change2(variable)
    i = 0
    while i < 3:
        print numbers[i]
        i += 1
    print variable[0]

main()
$ python test4.py 
4
13
12
15   # I expected 17! Why no 17?
$cat test4.py
#还不是一个通过值传递的示例!
全局变量
变量=[15]
def更改1(列表1):
列表1[1]=列表1[1]+5
def更改2(编号):
数字=[x+2表示数字中的x]
def main():
数字=[4,8,12]
更改1(数字)
#变量=15
变更2(可变)
i=0
而我<3:
印刷数字[i]
i+=1
打印变量[0]
main()
$python test4.py
4.
13
12
15#我以为是17!为什么是17号?

Python参数是通过引用传递的。您只能在
change1
中变异一个对象

但是,数值和字符串都是不可变的。您不能更改传入的不可变项的值并在调用方中看到该值的更改。另一方面,字典和列表是可变的,被调用函数对它们所做的更改将在函数返回时保留


更多信息:

Python参数通过引用传递。您只能在
change1
中变异一个对象

但是,数值和字符串都是不可变的。您不能更改传入的不可变项的值并在调用方中看到该值的更改。另一方面,字典和列表是可变的,被调用函数对它们所做的更改将在函数返回时保留


更多信息:

change1
中,您将列表中的值与
值+5
交换
change2
中,将5添加到
number
。结果是一个新对象,而不仅仅应用于传递的变量。 如果您来自C++:不,Python中没有
int&var

执行此操作时,您将获得预期的结果:

def change2(number):
    return number + 5

variable = 15
variable = change2(variable)
如果仍然不想返回值,可以创建一个
MutableInt

class MutableInt(object):

    def __init__(self, value = 0):
        self._value = int(value)

    def __add__(self, other):
        self._value += int(other)
        return self

    def __sub__(self, other):
        self._value -= int(other)
        return self

    ...

change1
中,将列表中的值与
value+5
交换
change2
中,将5添加到
number
。结果是一个新对象,而不仅仅应用于传递的变量。 如果您来自C++:不,Python中没有
int&var

执行此操作时,您将获得预期的结果:

def change2(number):
    return number + 5

variable = 15
variable = change2(variable)
如果仍然不想返回值,可以创建一个
MutableInt

class MutableInt(object):

    def __init__(self, value = 0):
        self._value = int(value)

    def __add__(self, other):
        self._value += int(other)
        return self

    def __sub__(self, other):
        self._value -= int(other)
        return self

    ...
因此,如果要更改现有对象,必须以某种方式引用它们,例如在

def change3(number):
    # `number[:]` is the whole existing list and you overwrite it
    number[:] = [x+2 for x in number]
更改列表时请注意
[…]

因此,如果要更改现有对象,必须以某种方式引用它们,例如在

def change3(number):
    # `number[:]` is the whole existing list and you overwrite it
    number[:] = [x+2 for x in number]

更改列表时请注意
[…]

所有示例都显示按值调用。Python只有按值调用。没有引用调用。python中的所有值都是引用(不可能将“对象”作为值)。因此,在传递给函数时复制的是引用。列表是可变的,因此可以通过共享引用改变其内容。在change2中,您将重新分配一个局部变量以指向另一个对象,与所有对局部变量的分配一样,该对象对任何调用范围都没有影响,因为它是按值调用的。

所有示例都显示了按值调用。Python只有按值调用。没有引用调用。python中的所有值都是引用(不可能将“对象”作为值)。因此,在传递给函数时复制的是引用。列表是可变的,因此可以通过共享引用改变其内容。在change2中,您将重新分配一个局部变量以指向另一个对象,这与所有对局部变量的分配一样,对任何调用范围都没有影响,因为它是按值调用的。

最终的答案是Python实际上是“按共享调用”,也称为“按对象调用”或“按对象引用调用”

这是一个很好的例子。从该条中:

有时,读过一点CS但没有读过很多CS(或者只是一种CS读得太多)的人会出现在comp.lang.python上,并浪费大量精力试图告诉大家python正在使用一些它并不真正使用的调用模型。结果总是证明,他们并不真正理解Python的模型,而且常常也不理解他们最喜欢的模型

但无论如何,您需要知道的唯一一件事是Python的模型既不是“按值调用”也不是“按引用调用”(因为在Python中使用这些术语的任何尝试都需要使用“-value”和“-reference”这两个词的非标准定义)。最准确的描述是CLU的“按对象调用”“或“通过共享调用””。或者,如果您愿意,“按对象调用引用”

如果你还没有阅读,你也应该阅读

Python的语义与CLU语言的语义最为相似