何时可以在函数调用中更改变量?

33 浏览
0 Comments

何时可以在函数调用中更改变量?

这个问题已经有了答案

理解Python函数参数传递的对象调用方式[重复]

在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_intappend_string 上面没有像我最初预期的那样发生,除了这与整数和字符串的不可变性有关之外。

admin 更改状态以发布 2023年5月23日
0
0 Comments

在"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]

"交换"会改变用于引用列表的变量名称,但仅在函数内部。尽管底层对象的突变是永久的,但变量的赋值取决于作用域。函数内的新 l1l2 可以视为其他名称,因为它们现在只是遮盖了函数签名中定义的原始变量 l1l2,这反过来又遮盖了主脚本中定义的 l1l2。然后突变应用于原始列表。

0