Python:为什么要使用int&列表函数参数是否不同对待? [英] Python: Why are int & list function parameters differently treated?

查看:115
本文介绍了Python:为什么要使用int&列表函数参数是否不同对待?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们都知道全局变量是错误的教条.当我开始学习python时,我将读取传递给函数的参数视为函数内部的局部变量.这似乎至少是事实的一半:

We all know the dogma that global variables are bad. As I began to learn python I read parameters passed to functions are treated as local variables inside the funktion. This seems to be at least half of the truth:

def f(i):
    print("Calling f(i)...")
    print("id(i): {}\n".format(id(i)))
    print("Inside f(): i += 1")
    i += 1
    print("id(i): {}".format(id(i)))
    return

i = 1
print("\nBefore function call...")
print("id(i): {}\n".format(id(i)))
f(i)

计算结果为:

Before function call...
id(i): 507107200

Calling f(i)...
id(i): 507107200

Inside f(): i += 1
id(i): 507107232

正如我现在所读,Python中函数的调用机制是按对象引用调用".这意味着自变量最初是通过其对象引用传递的,但是如果在函数内部对其进行了修改,则会创建一个 new 对象变量.对于我来说,避免使用一种功能意外修改全局变量的设计似乎很合理.

As I read now, the calling mechanism of functions in Python is "Call by object reference". This means an argument is initially passed by it's object reference, but if it is modified inside the function, a new object variable is created. This seems reasonable to me to avoid a design in which functions unintendedly modify global variables.

但是如果我们将列表作为参数传递会发生什么呢?

But what happens if we pass a list as an argument?

def g(l):
    print("Calling f(l)...")
    print("id(l): {}\n".format(id(l)))
    print("Inside f(): l[0] += 1")
    l[0] += 1
    print("id(l): {}".format(id(l)))
    return

l = [1, 2, 3]
print("\nBefore function call...")
print("id(l): {}\n".format(id(l)))
g(l)

结果是:

Before function call...
id(l): 120724616

Calling f(l)...
id(l): 120724616

Inside f(): l[0] += 1
id(l): 120724616

我们可以看到,对象引用保持不变!所以我们在一个全局变量上工作,不是吗?

As we can see, the object reference remains the same! So we work on a global variable, don't we?

我知道我们可以通过使用以下方法将列表的副本传递给函数来轻松解决此问题:

I know we can easily overcome this by passing a copy of the list to the function with:

g(l[:])

但是我的问题是:在Python中实现函数参数的两种不同行为的原因是什么?如果我们打算操纵一个全局变量,我们也可以像对整数一样使用"global"关键字作为列表,不是吗?这种行为与zen的禅意显性要好于隐性"如何一致?

But my question is: What is the reason the implement two different behaviors of function parameters in Python? If we intend to manipulate a global variable, we could also use the "global"-keyword for list like we would do for integers, couldn't we? How is this behavior consistent with the zen of python "explicit is better than implicit"?

推荐答案

Python有两种类型的对象-可变对象和不可变对象.大多数内置类型(如int,string或float)都是不可变的.这意味着它们无法更改.诸如list,dict或array之类的类型是可变的,这意味着可以更改它们的状态.几乎所有用户定义的对象也是可变的.

Python has two types of objects - mutable and inmutable. Most of build-in types, like int, string or float, are inmutable. This means they cannot change. Types like list, dict or array are mutable, which means that their state can be changed. Almost all user defined objects are mutable too.

当您执行i += 1时,会为i分配一个新值,即i + 1.这不会以任何方式使i发生变异,只是说它应该忘记i并将其替换为i + 1的值.然后i被一个全新的对象替换. 但是,当您在列表中执行i[0] += 1时,您对应该使用i[0] + 1替换元素0的列表说.这意味着id(i[0])将被新对象更改,并且列表i的状态也将更改,但是其身份保持不变-它与以前的对象相同,只是被更改.

When you do i += 1, you assign a new value to i, which is i + 1. This doesn't mutate i in any way, it just says that it should forget i and replace it with value of i + 1. Then i becomes replaced by a completely new object. But when you do i[0] += 1 in list, you say to the list that is should replace element 0 with i[0] + 1. This means that id(i[0]) will be changed with new object, and the state of list i will change, but it's identity remains the same - it's the same object it was, only changed.

请注意,在Python中,这对于字符串不是正确的,因为它们是不可变的,更改一个元素将复制具有更新值的字符串并创建新对象.

Note that in Python this is not true for strings, as they are immutable and changing one element will copy the string with updated values and create new object.

这篇关于Python:为什么要使用int&列表函数参数是否不同对待?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆