我对从函数内部改变(变异或附加)变量感到困惑 作为参考,我发现了关于functions that mutate the argument的这个问题。其中描述了在数组上执行此操作:
def add_thing(a):
a.append(2)
my_a = [1]
append_two(my_a)
my_a
>>> [1,2]
我们使用+ = [2]
得到相同的结果但是,如果我们使用字符串或整数尝试相同的事情:
def add_world (s):
s += " world"
my_str = "hello"
add_world(my_str)
my_str
>>> "hello"
它不会改变,整数也是如此,例如:
def add_one(i):
i += 1
x = 1
add_one(x)
x
>>> 1
我的问题是:
我应该如何识别我可以在像数组这样的函数中变异的对象,以及我需要直接分配哪些对象?
为什么+ =运算符不能像我期望的那样工作?我很确定这是my_var = my_var + thing的简写,它可以在一个函数中正常工作。
答案 0 :(得分:2)
您必须查看文档。通常:数字,字符串和tuple
是不可变的。
关于特定方法,还有一个通用规则:如果方法返回,那么它不会修改参数。修改参数的方法返回None
。
a += b
不可变,则 a = a + b
相当于a
。如果a
是可变的,则使用+=
将改变对象。基本上+=
只是一个方法调用(到__iadd__
)。在不可变对象的情况下,该方法返回一个新对象并且不会改变原始值,对于可变对象,该对象是变异的并且它自己返回。
答案 1 :(得分:2)
我应该如何识别我可以在像数组这样的函数中变异的对象,以及我需要直接分配哪些对象?
您需要知道您正在使用的对象类型,并阅读这些对象的文档,以了解哪些操作(如果有)会改变它们。不幸的是,在list
的情况下,这并没有以最容易获得的方式记录。最接近的是this,其中说:
像
x += 1
这样的扩充分配表达式可以重写为x = x + 1
,以实现类似但不完全相同的效果。在增强版本中,x仅评估一次。此外,在可能的情况下,实际操作是就地执行的,这意味着不是创建新对象并将其分配给目标,而是修改旧对象。
由于列表是可变的,这意味着可以进行就地操作。
为什么+ =运算符不能像我期望的那样工作?我很确定这是my_var = my_var + thing的简写,它可以在函数中正常工作。
如上面的引用所示,a += b
与a = a + b
并不完全相同。不同之处在于,对象a
有机会为a += b
定义可能与a + b
的行为不同的特殊行为。列表执行此操作以使+=
就地工作。