V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
damngoto
V2EX  ›  Python

Python 迷惑系列

  •  
  •   damngoto · 2022-07-29 11:06:14 +08:00 · 4452 次点击
    这是一个创建于 849 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 不一样,所以没有受到影响。

    23 条回复    2022-08-02 16:48:53 +08:00
    BeautifulSoup
        1
    BeautifulSoup  
       2022-07-29 11:17:59 +08:00
    应该是类实例和类对象的问题,a.stream = 'ece'修改的是类实例,CSStudent.stream = 'mech'修改的是类对象。
    a.stream = 'ece'是在对象内部新建的实例变量(可以理解为 self.stream),会“覆盖”类内全局变量 stream ;而 bc 那打印就是取的类内全局变量 stream
    如果真的做项目不要这么写,十分不规范
    lyang
        2
    lyang  
       2022-07-29 11:19:07 +08:00
    https://m.py.cn/jishu/jichu/32471.html
    创建实例时,类属性不会成为实例属性。当为它们分配值时,它们成为实例属性。
    codeMore
        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
    krixaar
        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 。
    damngoto
        6
    damngoto  
    OP
       2022-07-29 11:34:43 +08:00
    这个网站看起来不错,学习学习。
    damngoto
        7
    damngoto  
    OP
       2022-07-29 11:35:00 +08:00
    filwaline
        8
    filwaline  
       2022-07-29 12:12:10 +08:00   ❤️ 1
    https://github.com/satwikkansal/wtfpython#-class-attributes-and-instance-attributes

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

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

    这特么团队毒瘤吧。
    solopython
        22
    solopython  
       2022-07-30 23:36:08 +08:00
    最佳实践是使用类名来更改类变量的值。因为如果我们尝试通过使用一个对象来更改类变量的值,则会为该特定对象创建一个新的实例变量,它会隐藏类变量。
    fgwmlhdkkkw
        23
    fgwmlhdkkkw  
       2022-08-02 16:48:53 +08:00
    你就不能怀疑你自己的直觉吗?……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5989 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 03:02 · PVG 11:02 · LAX 19:02 · JFK 22:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.