TensorFlow的assign_add/assign_sub为何同时修改类与实例变量?
为什么TensorFlow的assign_add/assign_sub会同时修改类变量和实例变量?
这个现象的核心原因是Python中可变对象与不可变对象的行为差异,结合TensorFlow tf.Variable的特性导致的:
1. 普通Python类的行为解析
在普通Python类myc_base中:
- 类变量
a=1.是不可变类型(float)。不可变类型的特点是无法修改对象本身的内容,任何"修改"操作都会创建一个新的对象。 - 当实例调用
self.a += to_add时,实际执行逻辑是:- 读取类变量
a的初始值1. - 计算
1. + 5. = 6.,创建一个新的float对象6. - 将这个新对象赋值给实例属性
self.a
- 读取类变量
- 此时实例的
a已经脱离了对类变量的引用,拥有了独立的实例属性,所以后续修改只会影响实例自身,类变量保持不变。
你可以通过打印对象ID验证这一点:
print(f"Init: class.a id={id(myc_base.a)}, obj.a id={id(obj_base.a)}") # 初始时ID相同 obj_base.add(5.) print(f"After add: class.a id={id(myc_base.a)}, obj.a id={id(obj_base.a)}") # ID不同,说明是两个独立对象
2. TensorFlow类的行为解析
在TensorFlow类myc_tf中:
- 类变量
a=tf.Variable(1.)是可变类型。tf.Variable是封装数值的可变容器,允许直接修改内部存储的数值,不需要创建新的Variable对象。 - 当实例调用
self.a.assign_add(to_add)时:- 实例的
self.a在未被重新赋值的情况下,始终指向类变量的那个tf.Variable实例(可以用id(myc_tf.a) == id(obj_tf.a)验证) assign_add方法直接修改了这个可变对象内部的数值,而非创建新的Variable
- 实例的
- 因为类变量和实例变量指向的是同一个可变对象,修改对象内部值后,两者读取到的数值会同步变化。
而实例的b是在__init__中创建的独立tf.Variable,所以self.b.assign_add只会修改这个实例专属的Variable,不会影响其他实例或类属性。
总结
- 不可变类型(如int、float、str):"修改"操作会创建新对象,实例属性会脱离类变量的引用
- 可变类型(如tf.Variable、list、dict):修改操作直接改变对象内部内容,若实例属性未重新赋值,会始终指向类变量的同一个对象,导致类变量和实例变量同步变化
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

