我在程序中遇到了一个非常难以追踪的错误,其中类自迭代被外部函数操纵,并发现一些自变量可以更改,而有些则不能。 是否可以使用外部函数像 int 一样操作单个自变量而不传递整个类?
这是一些示例代码:
class TestClass(object):
def __init__(self):
self.my_var = 0
self.my_str = "Foo"
self.my_tuple = (1, 2, 3)
self.my_list = [1, 2, 3]
self.my_dict = {"one": 1, "two": 2, "three": 3}
self.manipulate_1()
self.manipulate_2()
def manipulate_1(self):
external_1(self.my_var, self.my_list, self.my_str, self.my_tuple, self.my_dict)
print(self.my_var)
print(self.my_list)
print(self.my_str)
print(self.my_tuple[0])
print(self.my_dict["one"])
#prints 0, 15, Foo, 1, 15
def manipulate_2(self):
external_2(self)
print("\n" + str(self.my_var))
# prints 1
def external_1(instance_var, instance_list, instance_str, instance_tuple, instance_dict):
instance_var += 1
del instance_list[0]
del instance_list[0]
instance_list[0] = 15
instance_str = "Bar"
list(instance_tuple)[0] = 15
instance_dict.update({"one": 15})
def external_2(instance):
instance.my_var += 1
a = TestClass()
只需将列表作为参数传递即可通过删除条目来操作列表,而变量只能在传递 self
时进行操作。
有没有办法操纵单个自变量。如果没有,传递 self
是否会带来任何性能或其他问题?
即,如果我想操作自变量,是否必须使用方法?
最佳答案
Python 的参数传递对于所有对象都是相同的 - 传递原始对象(不是“副本”,不是“引用”,不是“指向”的指针 - 它是传递的对象本身),无论对象的类型如何,是否可变等。然后,这些对象将作为局部变量绑定(bind)到其匹配参数的名称。
您观察到的差异实际上是完全不同的操作之间的差异的结果:重新绑定(bind)(本地)名称和改变对象。
由于参数是局部变量(实际上是局部名称),因此在函数体内重新绑定(bind)参数只会使该名称指向另一个对象,并且不会影响原始参数(除了减少引用计数器)。显然,这在函数本身之外绝对没有任何影响。
现在,当您改变您的参数之一时,由于您正在处理传递给函数的对象,因此这些更改非常明显地在函数外部可见。
这里:
def external_1(instance_var, instance_list, instance_str, instance_tuple, instance_dict):
# this one rebinds the local name `instance_var`
# to a new `int` object. Doesn't affect the object
# previously bound to `instance_var`
instance_var += 1
# those three statement mutate `instance_list`,
# so the effect is visible outside the function
del instance_list[0]
del instance_list[0]
instance_list[0] = 15
# this one rebinds the local name `instance_str`
# to the literal string "Bar". Same as for `instance_var`
instance_str = "Bar"
# this one creates a list from `instance_tuple`,
# mutate this list, and discard it. IOW it eats a
# couple processor cycles for nothing.
list(instance_tuple)[0] = 15
# and this one mutates `instance_dict` so the
# effect is visible outside the function
instance_dict.update({"one": 15})
这里:
def external_2(instance):
# this one mutates `instance` - it's actually
# syntactic sugar for
# `instance.__setattr__("my_var", instance.__getattribute__("my_var") + 1))`
instance.my_var += 1
正如我在评论中多次提到的,所有这些(以及更多)is explained in full details in Ned Batchelder's reference article .
关于python - 为什么使用外部函数传递和更改类自变量可以操作可迭代对象,但不能操作变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51875174/