class CSStudent: stream = 'cse' a = CSStudent() a.stream = 'ece' b = CSStudent() CSStudent.stream = 'mech' c = CSStudent() print(a.stream) # ece print(b.stream) # mech print(c.stream) # mech
直觉上看的话 a 应该也要被改才对,不知道 py 的机制。 id 看的话 id(a.stream) 的地址确实与 bc 不一样,所以没有受到影响。
![]() | 1 BeautifulSoup 2022-07-29 11:17:59 +08:00 应该是类实例和类对象的问题,a.stream = 'ece'修改的是类实例,CSStudent.stream = 'mech'修改的是类对象。 a.stream = 'ece'是在对象内部新建的实例变量(可以理解为 self.stream),会“覆盖”类内全局变量 stream ;而 bc 那打印就是取的类内全局变量 stream 如果真的做项目不要这么写,十分不规范 |
![]() | 2 lyang 2022-07-29 11:19:07 +08:00 https://m.py.cn/jishu/jichu/32471.html 创建实例时,类属性不会成为实例属性。当为它们分配值时,它们成为实例属性。 |
![]() | 3 codeMore 2022-07-29 11:21:40 +08:00 CSStudent.tream 是类变量,改变类变量,所有的实例都会受到影响。 a.stream 为什么没有受到影响,是因为 a.stream 其实算是新建的实例变量 stream 了,已经不是类变量的 stream 了。参考文章:http://c.biancheng.net/view/2283.html |
![]() | 4 BBrother 2022-07-29 11:21:42 +08:00 ![]() |
5 krixaar 2022-07-29 11:22:34 +08:00 ![]() https://docs.python.org/zh-cn/3/tutorial/classes.html#random-remarks > 如果同样的属性名称同时出现在实例和类中,则属性查找会优先选择实例 所以 b 和 c 的 实例 没有 stream ,就找了 类 的 stream ,而 a 的实例有 stream ,所以直接用实例的 stream 。 |
![]() | 6 damngoto OP 这个网站看起来不错,学习学习。 |
8 filwaline 2022-07-29 12:12:10 +08:00 ![]() https://github.com/satwikkansal/wtfpython#-class-attributes-and-instance-attributes 其实在 wtf-python 里就有写,你肯定没看(滑稽 |
![]() | 9 RockShake 2022-07-29 12:18:00 +08:00 Python Tutor 可视化很直观 |
![]() | 10 ruanimal 2022-07-29 14:10:55 +08:00 学一门语言,还是需要认真看看语法的。。 |
![]() | 11 killva4624 2022-07-29 14:14:13 +08:00 类属性一般都不改吧,太不可控了,很难去评估有些哪些对象会收到影响。 |
14 filwaline 2022-07-29 15:35:38 +08:00 via Android @damngoto 这怎么就葵花宝典了哈哈哈,先浏览几遍,对 Python 有什么坑留点印象,以后遇到问题了好快速解决,而不是一头雾水 |
![]() | 16 AV1 2022-07-29 17:17:16 +08:00 python 的 class 设计缺陷,定义时没有区分静态成员和实例成员。 a.stream 被修改之前指向静态成员,修改之后就变成实例成员了。 JS 的 class 吸取了这个教训,增加 static 修饰符,而且不允许通过实例直接访问静态成员。 |
![]() | 17 Richard14 2022-07-29 17:30:21 +08:00 ![]() |
![]() | 19 AV1 2022-07-29 21:06:07 +08:00 via Android @Richard14 嗯,不是“缺陷”,是缺点。说明 Python 当初设计欠缺考虑,出现了不同于其他语言的反直觉现象了。这个问题我都在 v2 上遇到几次了。 JS 的以前的原型写法也会遇到类似 Python 这个问题,但 class 就没这个问题了,不会出现静态成员和实例成员混淆的现象,这方面更符合其他主流语言的思维。在这一点还是可以笑话一下 Python 的。 |
![]() | 21 documentzhangx66 2022-07-30 05:08:45 +08:00 ![]() 无论结论是什么,谁这样写代码,就开除谁。 这特么团队毒瘤吧。 |
22 solopython 2022-07-30 23:36:08 +08:00 最佳实践是使用类名来更改类变量的值。因为如果我们尝试通过使用一个对象来更改类变量的值,则会为该特定对象创建一个新的实例变量,它会隐藏类变量。 |
![]() | 23 fgwmlhdkkkw 2022-08-02 16:48:53 +08:00 你就不能怀疑你自己的直觉吗?…… |