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
raiz
V2EX  ›  Python

关于 python(3) 类属性和数据属性的问题, 为什么 可以用 self.cls_attr 作为右值,作为左值却会覆盖为 数据属性?

  •  
  •   raiz · 2015-08-07 13:23:49 +08:00 · 2340 次点击
    这是一个创建于 3396 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class A():
        cls_attr = 1
    
        def fun1(self):
            print(self.cls_attr)
    
        def fun2(self):
            self.cls_attr += 1
    
    a = A()
    
    print(a.cls_attr)    # 1
    
    fun1()              # 1
    
    fun2()
    
    print(a.cls_attr)    # 1
    
    fun1()           #2
    
    第 1 条附言  ·  2015-08-07 18:22:42 +08:00
    上面的代码有问题, 下面是 运行过的
    ```
    >>> class A():
    ... cls_attr = 1
    ... def fun1(self):
    ... print(self.cls_attr)
    ... def fun2(self):
    ... self.cls_attr += 1
    ...
    >>> a = A()
    >>> a.cls_attr
    1
    >>> a.fun1()
    1
    >>> a.fun2()
    >>> a.cls_attr
    2
    >>> A.cls_attr
    1
    >>> a.fun1()
    2
    ```
    10 条回复    2015-08-08 09:33:16 +08:00
    caoyue
        1
    caoyue  
       2015-08-07 16:50:23 +08:00
    我的理解是 在实例空间中找不到 cls_attr 也会去类空间中找
    所以 print(a.cls_attr) 是 1
    然后 self.cls_attr += 1 在实例空间中创造了 cls_attr
    所以 print(a.cls_attr) 是 2 (楼主这里写错了?)
    如果你看 A.cls_attr,应该还是 1
    Cynic222
        2
    Cynic222  
       2015-08-07 17:02:15 +08:00
    你确定你的代码你跑过?
    imlonghao
        3
    imlonghao  
       2015-08-07 17:18:48 +08:00 via Android
    你下面调用的时候
    哪里来的 fun1 ?
    哪里来的 fun2 ?
    raiz
        4
    raiz  
    OP
       2015-08-07 18:21:46 +08:00
    @imlonghao
    @Cynic222 不好意思 代码实在这里现码的, 打错, 都是 通过 a.funN() 调用
    @caoyue
    对 a.cls_attr 是2 我本来想打的是 A.cls_attr 是1

    下面是在 consola 中打的
    ```
    >>> class A():
    ... cls_attr = 1
    ... def fun1(self):
    ... print(self.cls_attr)
    ... def fun2(self):
    ... self.cls_attr += 1
    ...
    >>> a = A()
    >>> a.cls_attr
    1
    >>> a.fun1()
    1
    >>> a.fun2()
    >>> a.cls_attr
    2
    >>> A.cls_attr
    1
    >>> a.fun1()
    2
    ```
    zealot0630
        5
    zealot0630  
       2015-08-07 18:24:59 +08:00
    楼主看一下A.__dict__和a.__dict__就明白了
    raiz
        6
    raiz  
    OP
       2015-08-07 18:25:06 +08:00
    @caoyue self.cls_attr += 1 不应该意识 “赋值给为声明的变量“吗 或者 直接访问 类属性吗
    raiz
        7
    raiz  
    OP
       2015-08-07 18:37:56 +08:00
    @zealot0630 嗯 我看到了类和实例的字典里都有 cls_attr 这个变量, 实例的是在 调用 fun2() 之后生成的, 我问题就在于为什么 读 self.cls_attr 的时候能访问到 类属性,而不会提示找不到, 而赋值的时候又会去生成一个实例变量

    >>> a.__dict__
    {'cls_attr': 2}
    >>> A.__dict__
    {'__module__': '__main__', '__doc__': None, 'fun1': <function fun1 at 0x00000000025CA5F8>, 'cls_attr': 1, 'fun2': <function fun2 at 0x00>}
    caoyue
        8
    caoyue  
       2015-08-07 19:22:09 +08:00
    @raiz
    如果这里是
    v = self.cls_attr + 1
    self.cls_attr = v
    是不是好理解点……

    可以看看 Python 的 namespace 和 scope rules 相关的内容
    要是简单来说的话那就是 Python 就是这么设计的,而且不这么设计的话会带来别的问题 :)
    RIcter
        9
    RIcter  
       2015-08-08 06:15:21 +08:00 via iPhone
    a 是 A 的 instance,對 a 做的操作一般來說是不會影響到 A 的⋯
    Feiox
        10
    Feiox  
       2015-08-08 09:33:16 +08:00
    每个实例会复制一份类属性,你修改的只是这个属性的副本,并不会影响其本身。如果想修改类属性,请使用 A.cls_attr += 1 的方式修改。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2673 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:38 · PVG 20:38 · LAX 04:38 · JFK 07:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.