King丨小义 发表于 2021-11-8 14:42:57

关于python类对象的问题

本帖最后由 King丨小义 于 2021-11-8 14:45 编辑

class M:
    def __init__(self, x=1):
      print("hellowrold")
      self.x = x

class A:
    m = M()
    val = 10

# 代码运行到这个位置,程序输出一个helloworld

a = A()       # 此时实例化A对象,程序不输出helloworld
print(a.m.x)# 1

b = A()       # 此时实例化A对象,程序不输出helloworld
print(b.m.x)# 1

a.m.x = 10    # 修改a.m.x
print(b.m.x)# 奇怪的是b.m.x也改变了

# 之后我在A中又加入了一个变量val,发现改变a.val对b.val无影响
print("a.val = ", a.val,", b.val = ", b.val)       # a.val =10 , b.val =10
a.val = 520
print("a.val = ", a.val,", b.val = ", b.val)       # a.val =520 , b.val =10

这个程序看起来a和b共用了一个M的实例化对象,但是没有共用val,这是为什么?{:9_241:}

hrpzcf 发表于 2021-11-8 14:42:58

本帖最后由 hrpzcf 于 2021-11-8 15:56 编辑

首先m和val都是类属性,实例化a和b的时候,各自实例中生成了和类属性同名的实例属性,两个实例各自的实例属性m和val都指向了A类属性m和val,这时候a和b中这两个属性值都是一样的,验证一下就知道:print(a.m is b.m, a.val is b.val)。所以不论是改变a.m.x还是b.m.x,改变的都是同一个m的x属性(不是改变m),而改变a.val和b.val就不一样了,它们改变了各自实例中val的值,但互不影响(前面已经说了,实例化的时候各自生成了A类属性同名的实例属性,最后加一句就知道:print(A.val)#还是10)

逃兵 发表于 2021-11-8 15:01:30

都共用了,只是你用赋值的方式把val变量的指向给改了

我们把val改成列表,使用.append方法不改变列表本身的话

class M:
    def __init__(self, x=1):
      print("hellowrold")
      self.x = x

class A:
    m = M()
    val =

# 代码运行到这个位置,程序输出一个helloworld

a = A()       # 此时实例化A对象,程序不输出helloworld
print(a.m.x)# 1

b = A()       # 此时实例化A对象,程序不输出helloworld
print(b.m.x)# 1

a.m.x = 10    # 修改a.m.x
print(b.m.x)# 奇怪的是b.m.x也改变了

# 之后我在A中又加入了一个变量val,发现改变a.val对b.val无影响
print("a.val = ", a.val,", b.val = ", b.val)
a.val.append(520)
print("a.val = ", a.val,", b.val = ", b.val)

King丨小义 发表于 2021-11-8 15:27:25

本帖最后由 King丨小义 于 2021-11-8 15:30 编辑

逃兵 发表于 2021-11-8 15:01
都共用了,只是你用赋值的方式把val变量的指向给改了

我们把val改成列表,使用.append方法不改变列表本 ...

答案不是很对。
其实是因为我在写a.val=520之后,a.val 和 b.val的含义已经不一样了,a.val变成了实例化对象的一个扩展属性,而b.val仍是类的全局属性(对所有对象共享的那个)

class M:
    def __init__(self, x=1):
      print("hellowrold")
      self.x = x

class A:
    m = M()
    val = 10

a = A()
b = A()
print(a.__dict__)   # 空字典
print(b.__dict__)   # 空字典
print(A.__dict__)   # 里面有 m 和 val
print("a.val = ", a.val,", b.val = ", b.val)   # a.val =10 , b.val =10

a.val = 520    # 看似是修改a.val,实际是新创建了一个a的属性
print(a.__dict__)   # {'val': 520}
print(b.__dict__)   # 仍是空字典
print(A.__dict__['val'])   # 10



简单说,a.val = 520 之后,a中其实有两个val属性,只是访问的时候优先访问520的那个
页: [1]
查看完整版本: 关于python类对象的问题