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

python 属性访问疑问

  •  1
     
  •   mink · 2016-01-07 16:27:09 +08:00 · 3156 次点击
    这是一个创建于 3003 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class B(object):
        def __init__(self):
            self.name ='mink'
    
    class A(B):
        name = 'kk'
    
    a = A()
    
    # pirnt 'mink'
    print a.name
    

    我访问 a.name 会访问 B 的实例属性,而不是 A 的类属性,是不是我在创建实例 a 的时候默认用 B 的构造方法创建的啊?

    15 条回复    2016-01-08 10:53:07 +08:00
    Kilerd
        1
    Kilerd  
       2016-01-07 16:35:16 +08:00
    建议看看 类的继承和派生 相对应内容
    lovedboy
        2
    lovedboy  
       2016-01-07 16:41:11 +08:00
    class B(object):

    def __new__(self):
    print "new:",self.name
    return super(B,self).__new__(self)
    def __init__(self):
    print 'init:', self.name
    self.name ='mink'
    pass

    class A(B):
    name = 'kk'

    a = A()

    # pirnt 'mink'
    print a.name
    ljdawn
        3
    ljdawn  
       2016-01-07 16:57:39 +08:00
    实例的属性存储在实例的__dict__中,类属性存储在类的__dict__中.查找时先查找实例的__dict__,然后才是类的__dict__
    knightdf
        4
    knightdf  
       2016-01-07 16:59:32 +08:00
    __new__才是实例构造器,__init__是实例初始化的, new 后自动调用 init ,然后你就懂了
    hzm0318hzm
        5
    hzm0318hzm  
       2016-01-07 17:01:11 +08:00
    A 也需要__init__函数,在里面赋值就行了
    cizixs
        6
    cizixs  
       2016-01-07 17:05:25 +08:00
    类 A 可粗略写成这样:

    class A(object):
    name = 'kk'

    def __init__(self):
    self.name ='mink'

    包括了实例属性和类属性, python 访问的时候会先访问实例属性,然后是类属性,你可以用 a.__class__.ame 来访问类属性。
    lixiaohan
        7
    lixiaohan  
       2016-01-07 17:12:43 +08:00
    对于 A 来说 name 是它的类变量 而不是实例变量,其实它本身没有实例变量, 所以就用 B 的 就是这个结果了。
    playniuniu
        8
    playniuniu  
       2016-01-07 17:15:27 +08:00
    那是必须的,和继承没关系,想要打出 kk ,需要 print( A.name) 这才是类的值, a.name 已经是类的一个实例了
    mink
        9
    mink  
    OP
       2016-01-07 17:35:41 +08:00
    感谢你们的回答,我想问的是这样的。当 A 的实例 a 创建以后, a 的__dict__的空的,但是我在通过 A 继承 B 并且 B 中设置__init__。 实例 a 的__dict__里有了 name 这个属性,但是她是来自 B 的__init__。


    ```python
    class B(object):

    def __new__(cls):
    print 'new:', cls.name
    # A
    print cls.__name__
    return super(B, cls).__new__(cls)

    def __init__(self):
    print 'init:', self.name
    self.name = 'mink'

    class A(B):
    name = 'kk'

    a = A()

    print a.name
    ```
    这里我打印了一下 cls.__name__ 竟然是 A ,  cls 参数不是当前类么,有点费解
    tonghuashuai
        10
    tonghuashuai  
       2016-01-07 17:50:54 +08:00
    这样就好了

    class B(object):
    def __init__(self):
    self.name ='mink'

    class A(B):
    # A 也要有 init 方法
    def __init__(self):
    self.name ='kk'

    a = A()

    # pirnt 'kk'
    print a.name
    billlee
        11
    billlee  
       2016-01-07 21:11:32 +08:00
    就是实例的属性会覆盖掉类属性嘛
    vixvix
        12
    vixvix  
       2016-01-07 22:27:20 +08:00
    >>> class B(object):
    ... def __init__(self):
    ... self.name ='mink'
    ...
    >>> class A(B):
    ... name = 'kk'
    ...
    >>> a = A()
    >>>
    >>> # pirnt 'mink'
    ... print a.name
    mink
    >>> print A.name
    kk
    >>>
    rxkh
        13
    rxkh  
       2016-01-08 10:30:18 +08:00
    print A.name
    mink
        14
    mink  
    OP
       2016-01-08 10:51:10 +08:00
    其实我想知道实例创建时初始化过程,如果

    class B(object):
    def __init__(self):
    self.name = 'mink'

    class A(object):
    name = 'kk'

    a = A()

    # pritn {'name': 'mink'}
    # print 'mink'
    print a.__dict__
    print a.name

    我现在确定的是当实例 a 被创建出来时,如果 A 类没有初始化函数__init__就会在父类找。如果找到就执行父类的__init__,如果找不到几继续往上找。以下是测试的

    class C(object):
    def __init__(self):
    print 'in c'
    self.name = 'c mink'

    class B(object):
    def __init__(self):
    print 'in b'
    self.age = 3

    class A(B, C):
    name = 'kk'

    a = A()

    # print {'age': 3}
    # pirnt 'kk'
    print a.__dict__
    print a.name

    因为他在 b 中找到了__init__就不往上继续查了,这样 a.name 就会返回类的 name 也就是 kk

    class C(object):
    def __init__(self):
    print 'in c'
    self.name = 'c mink'

    class B(object):
    age = 3

    class A(B, C):
    name = 'kk'

    a = A()

    # print {'name': 'c mink'}
    # pirnt 'c mink'
    print a.__dict__
    print a.name
    mink
        15
    mink  
    OP
       2016-01-08 10:53:07 +08:00
    这样就找到了,所以能找到 C 中的 'c mink'。 感谢你们的回答
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3210 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:39 · PVG 19:39 · LAX 04:39 · JFK 07:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.