Python中为什么函数内可以直接修改外部类实例的属性?
例如:
class C(object):
def init(self):
self.a = 0
def f ©:
c.a += 1
c.b = 2
c0 = C()
print(c0.a)
f(c0)
print(c0.a, c0.b)
输出:
0
1 2
这样感觉很像全局变量。这应该怎么理解?请问有没有相关的文档可以阅读呢?
Python中为什么函数内可以直接修改外部类实例的属性?
实例化时候修改类中的成员变量~?
这个问题涉及到Python的作用域和命名空间规则,核心在于属性访问和变量赋值的区别。
简单来说,在函数内部,obj.attr = value 这种操作不是在修改一个“外部变量”,而是在对一个已存在的对象 obj 进行属性操作。Python查找 obj 这个名称时,遵循 LEGB 规则,在你的例子中,它很可能在外部作用域找到了这个对象引用。找到之后,obj.attr = value 就变成了“请求对象 obj 设置其属性 attr”,这个操作是作用在对象本身上的,与函数的作用域无关。
这里的关键是区分:
- 修改对象属性 (
obj.attr = value): 这是允许的,因为你只是使用了对象引用。 - 重新绑定变量名 (
obj = new_value): 这会在函数的局部作用域创建一个新的局部变量obj,而不会影响外部作用域的同名变量。
看个对比代码就清楚了:
class MyClass:
def __init__(self):
self.value = 10
def modify_attr(obj):
"""这个函数可以成功修改外部对象的属性"""
obj.value = 20 # 通过传入的对象引用,修改其属性
def rebind_variable(obj):
"""这个函数无法修改外部变量本身"""
obj = MyClass() # 这只会在函数内部创建一个新的局部变量 `obj`
obj.value = 30
# 测试
my_obj = MyClass()
print(f"初始值: {my_obj.value}") # 输出: 初始值: 10
modify_attr(my_obj)
print(f"调用 modify_attr 后: {my_obj.value}") # 输出: 调用 modify_attr 后: 20
rebind_variable(my_obj)
print(f"调用 rebind_variable 后: {my_obj.value}") # 输出: 调用 rebind_variable 后: 20 (值未变)
总结一下: 你能修改属性是因为你操作的是对象本身,而不是变量名绑定的关系。
c0 = C() 实例化了 C 之后 C 原本有 c0 就是一个 class 类,里面有成员变量 c0.a
或者说每一个实例化的 C 类里面都默认有一个成员变量 a=0
print(c0.a) 所以输出了 0
f(c0)把 c0 里面默认的 a 变量自增了 1 所以 c0.a 在 c.a += 1 是 1(原本默认是 0)
又新增了一个 b=2 所以最后输出的时候是 1 2
不知道我这样理解的对不对,等大佬来解答一下
Python 和 Java 等面向对象的编程语言在函数调用的时候都是传递引用的

