鱼C论坛

 找回密码
 立即注册
查看: 1257|回复: 3

[已解决]关于python类对象的问题

[复制链接]
发表于 2021-11-8 14:42:57 | 显示全部楼层 |阅读模式
30鱼币
本帖最后由 King丨小义 于 2021-11-8 14:45 编辑
  1. class M:
  2.     def __init__(self, x=1):
  3.         print("hellowrold")
  4.         self.x = x

  5. class A:
  6.     m = M()
  7.     val = 10

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

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

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

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

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


这个程序看起来a和b共用了一个M的实例化对象,但是没有共用val,这是为什么?
最佳答案
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)

最佳答案

查看完整内容

首先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类属性同 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-8 14:42:58 From FishC Mobile | 显示全部楼层    本楼为最佳答案   
本帖最后由 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)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-8 15:01:30 | 显示全部楼层
都共用了,只是你用赋值的方式把val变量的指向给改了

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

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

  5. class A:
  6.     m = M()
  7.     val = [10]

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

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

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

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

  15. # 之后我在A中又加入了一个变量val,发现改变a.val对b.val无影响
  16. print("a.val = ", a.val,", b.val = ", b.val)
  17. a.val.append(520)
  18. print("a.val = ", a.val,", b.val = ", b.val)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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仍是类的全局属性(对所有对象共享的那个)

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

  5. class A:
  6.     m = M()
  7.     val = 10

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

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

复制代码


简单说,a.val = 520 之后,a中其实有两个val属性,只是访问的时候优先访问520的那个
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-12 10:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表