何时可以在函数调用中更改变量?
何时可以在函数调用中更改变量?
这个问题已经有了答案:
在Python中,我们可以在不返回任何东西的情况下,改变一些类型的对象。但是对于某些对象来说,这是不可能的。
例如,如果我们将一个字典传递给一个函数并在函数中对其进行更改,那么原始的字典将被更改:
def add_key(d, key): d[key] = True d = {} print d # {} add_key(d, 1) print d # {1: True}
相比之下,我们不能像这样更改整数:
def increment_int(i): i += 1 i = 1 print i # 1 increment_int(i) print i # still 1!
起初我认为,也许规则仅仅是不可变对象不能以这种方式在函数内部被更改。类似的例子对字符串也没有用:
def append_string(s1, s2): s1 += s2 s = "hello" print s # "hello" append_string(s, " world") print s # "hello", not "hello world" :(
我很困惑,因为似乎对于在函数内部应用于可变对象的某些操作,之后将是可见的,而另一些则不是。例如,将项附加到列表的操作确实可以用:
def append_list(l, val): l.append(val) l = [] print l # [] append_list(l, 1) print l # [1]
而交换两个列表的名称就不行:
def swap_lists(l1, l2): l1, l2 = l2, l1 l1 = [1] l2 = [2] print l1, l2 # [1] [2] swap_lists(l1, l2) print l1, l2 # still [1] [2], even though lists are mutable!
另一个例子,似乎具有奇怪和意外的行为:
def swap_then_append(l1, l2): l1, l2 = l2, l1 l1.append(1) l2.append(2) l1 = [] l2 = [] print l1, l2 # [] [] swap_then_append(l1, l2) print l1, l2 # [2] [1]
有人能解释这里正在发生什么吗?
编辑:这个问题可能是重复的,那里的答案部分地向我解释了正在发生的事情,但我仍然不明白为什么,例如上面的swap_lists
函数实际上并没有交换列表。现在我进一步思考时,我仍然不明白为什么increment_int
和 append_string
上面没有像我最初预期的那样发生,除了这与整数和字符串的不可变性有关之外。
admin 更改状态以发布 2023年5月23日
在"dupa target"中的解释已经很清楚了,但我会在 "swap_then_append " 中讲讲发生了什么。
def swap_then_append(l1, l2): print l1,l2 # [3],[4] l1, l2 = l2, l1 print l1,l2 # [4] [3] l1.append(1) l2.append(2) l1 = [3] l2 = [4] print l1, l2 # [3] [4] swap_then_append(l1, l2) print l1, l2 # [3,2] [4,1]
"交换"会改变用于引用列表的变量名称,但仅在函数内部。尽管底层对象的突变是永久的,但变量的赋值取决于作用域。函数内的新 l1
和 l2
可以视为其他名称,因为它们现在只是遮盖了函数签名中定义的原始变量 l1
和 l2
,这反过来又遮盖了主脚本中定义的 l1
和 l2
。然后突变应用于原始列表。