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.stream 是类变量,改变类变量,所有的实例都会受到影响。
a.stream 为什么没有受到影响,是因为 a.stream 其实算是新建的实例变量 stream 了,已经不是类变量的 stream 了。参考文章:http://c.biancheng.net/view/2283.html |
4
BBrother 2022-07-29 11:21:42 +08:00 1
|
5
krixaar 2022-07-29 11:22:34 +08:00 3
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 1
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
DOLLOR 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 1
|
19
DOLLOR 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 1
无论结论是什么,谁这样写代码,就开除谁。
这特么团队毒瘤吧。 |
22
solopython 2022-07-30 23:36:08 +08:00
最佳实践是使用类名来更改类变量的值。因为如果我们尝试通过使用一个对象来更改类变量的值,则会为该特定对象创建一个新的实例变量,它会隐藏类变量。
|
23
fgwmlhdkkkw 2022-08-02 16:48:53 +08:00
你就不能怀疑你自己的直觉吗?……
|