Python 迷惑系列

2022-07-29 11:06:14 +08:00
 damngoto
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 不一样,所以没有受到影响。

4269 次点击
所在节点    Python
23 条回复
BeautifulSoup
2022-07-29 11:17:59 +08:00
应该是类实例和类对象的问题,a.stream = 'ece'修改的是类实例,CSStudent.stream = 'mech'修改的是类对象。
a.stream = 'ece'是在对象内部新建的实例变量(可以理解为 self.stream),会“覆盖”类内全局变量 stream ;而 bc 那打印就是取的类内全局变量 stream
如果真的做项目不要这么写,十分不规范
lyang
2022-07-29 11:19:07 +08:00
https://m.py.cn/jishu/jichu/32471.html
创建实例时,类属性不会成为实例属性。当为它们分配值时,它们成为实例属性。
codeMore
2022-07-29 11:21:40 +08:00
CSStudent.stream 是类变量,改变类变量,所有的实例都会受到影响。
a.stream 为什么没有受到影响,是因为 a.stream 其实算是新建的实例变量 stream 了,已经不是类变量的 stream 了。参考文章:http://c.biancheng.net/view/2283.html
BBrother
2022-07-29 11:21:42 +08:00
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 。
damngoto
2022-07-29 11:34:43 +08:00
这个网站看起来不错,学习学习。
damngoto
2022-07-29 11:35:00 +08:00
filwaline
2022-07-29 12:12:10 +08:00
https://github.com/satwikkansal/wtfpython#-class-attributes-and-instance-attributes

其实在 wtf-python 里就有写,你肯定没看(滑稽
RockShake
2022-07-29 12:18:00 +08:00
Python Tutor 可视化很直观
ruanimal
2022-07-29 14:10:55 +08:00
学一门语言,还是需要认真看看语法的。。
killva4624
2022-07-29 14:14:13 +08:00
类属性一般都不改吧,太不可控了,很难去评估有些哪些对象会收到影响。
damngoto
2022-07-29 14:27:46 +08:00
@filwaline 老哥又来了,一上来就练葵花宝典不好吧。
damngoto
2022-07-29 14:53:15 +08:00
@ruanimal 你说的是官网吗?
filwaline
2022-07-29 15:35:38 +08:00
@damngoto 这怎么就葵花宝典了哈哈哈,先浏览几遍,对 Python 有什么坑留点印象,以后遇到问题了好快速解决,而不是一头雾水
damngoto
2022-07-29 15:58:27 +08:00
@filwaline 你说的有道理,但是不太适合我。我就是心血来潮看一下,一年写不了几行代码。
DOLLOR
2022-07-29 17:17:16 +08:00
python 的 class 设计缺陷,定义时没有区分静态成员和实例成员。
a.stream 被修改之前指向静态成员,修改之后就变成实例成员了。
JS 的 class 吸取了这个教训,增加 static 修饰符,而且不允许通过实例直接访问静态成员。
Richard14
2022-07-29 17:30:21 +08:00
@DOLLOR 实例未定义向方法引用,语言特性到你这说成语言缺陷了,js 的 class 可大哥别笑二哥了

@damngoto 有没有一种可能,怪的是 OP ,向上替换的特性不了解,然后还一定要用类属性,这又不是连函数和变量都没有的 java ,python 这有很多神奇的东西,比如全局变量。所以 OP 要借助类属性实现什么设计?
damngoto
2022-07-29 18:09:19 +08:00
@Richard14 网上随手看到的一个例子:)
DOLLOR
2022-07-29 21:06:07 +08:00
@Richard14
嗯,不是“缺陷”,是缺点。说明 Python 当初设计欠缺考虑,出现了不同于其他语言的反直觉现象了。这个问题我都在 v2 上遇到几次了。
JS 的以前的原型写法也会遇到类似 Python 这个问题,但 class 就没这个问题了,不会出现静态成员和实例成员混淆的现象,这方面更符合其他主流语言的思维。在这一点还是可以笑话一下 Python 的。
ipwx
2022-07-29 21:53:47 +08:00
@damngoto 你把类属性理解成对象属性的默认值就行。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/869414

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX