新人求助, 为什么实例属性没有覆盖类属性 - V2EX
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
woshicai
V2EX    Python

新人求助, 为什么实例属性没有覆盖类属性

  •  
  •   woshicai 2016-10-31 20:58:17 +08:00 3025 次点击
    这是一个创建于 3276 天前的主题,其中的信息可能已经有所发展或是发生改变。
    # lz 最近看廖雪峰的 python3 教程实战, 写代码时遇到一个问题, 此为背景
    暂时只贴部分代码,其余部分代码放在 github 上:
    https://github.com/hfutcbl/python-liaoxuefeng_practice/tree/master/aiohttpPractice

    python 版本:
    python3 --version
    Python 3.5.2

    代码:
    类的代码
    class User(Model):
    __table__ = 'users'

    id = StringField(primary_key=True, default=next_id, ddl='varchar(50)')
    email = StringField(ddl='varchar(50)')
    passwd = StringField(ddl='varchar(50)')
    admin = BooleanField()
    name = StringField(ddl='varchar(50)')
    image = StringField(ddl='varchar(500)')
    created_at = FloatField(default=time.time)
    调用代码
    u = User(name='Test1', email='[email protected]', passwd='1234567890', image='about:blank')
    ......
    def getValueOrDefault(self, key):
    print('email:%s, passwd:%s, name:%s, image:%s' % (self['email'], self['passwd'], self['name'], self['image']))
    print(self.email, self.passwd, self.name, self.image, '\n','self:', self)

    结果:
    email:[email protected], passwd:1234567890, name:Test1, image:about:blank
    [email protected] <StringField, varchar(50):None> <StringField, varchar(50):None> <StringField, varchar(500):None>
    self: {'email': '[email protected]', 'name': 'Test1', 'image': 'about:blank', 'passwd': '1234567890'}

    用 self[key] 访问可以正常获取数据,但用 self.key 只能获得传入的 4 个参数中的其中一个正确数据,比如这次是 email ,每次运行能够获取正确数据的 key 值不一样,运行多次亲测:
    email:[email protected], passwd:1234567890, name:Test1, image:about:blank
    <StringField, varchar(50):None> 1234567890 <StringField, varchar(50):None> <StringField, varchar(500):None>
    self: {'passwd': '1234567890', 'email': '[email protected]', 'image': 'about:blank', 'name': 'Test1'}

    有知道的大神能解答下吗?
    10 条回复    2016-11-01 17:39:52 +08:00
    woshicai
        1
    woshicai  
    OP
       2016-10-31 23:23:50 +08:00
    自顶一记
    没人不开心
    GreatMartial
        2
    GreatMartial  
       2016-11-01 00:28:48 +08:00 via Android
    不看你的代码,就看你的标题。
    实例属性的查询方式是:先查询实例的属性,如果没有查询到,才会向类里查询相应的属性。
    我是小白,可能说的不严谨。
    这个知识点我是在博客园里,有一篇专门讲类与实例属性继承的文章里学习到的
    cheetah
        3
    cheetah  
       2016-11-01 00:43:48 +08:00
    这代码格式没法看啊
    Trim21
        4
    Trim21  
       2016-11-01 00:52:04 +08:00 via Android
    问题抽象了,同时把代码也抽象一下吧。。。
    woshicai
        5
    woshicai  
    OP
       2016-11-01 08:25:55 +08:00
    @GreatMartial 是啊 print(self)可以看到实例的属性是我初始化实例的数据 但是用 self.key 访问到的确实类的属性
    @cheetah v 站貌似不支持 markdown
    @Trim21

    好吧,把问题抽象一下。
    简单的说就是我想获取 self 的属性, 用 self[key]能够正常获取我传入的数据, self.key 会出现异常(会返回类的 key 属性 default 值), print(self)显示实例的 key 值对应的是我传入的数据, 所以有疑惑。 想知道 self[key]和 self.key 的区别,为什么返回的结果不一样。
    slideclick
        6
    slideclick  
       2016-11-01 09:06:14 +08:00
    self.key 是标准获得实例属性的 python 语法。除非实例里面没有,才会去读类级别变量。至于 self[key]为什么可以,那个是 Django 框架设计的,不是 python 语法
    woshicai
        7
    woshicai  
    OP
       2016-11-01 09:36:35 +08:00
    @slideclick 感谢解答。
    尴尬的是我用的不是 Django 框架, 前面没说清楚, 我是让类 User 是继承 dict 类, 所以 self[key]的方式是可以的。
    而且 print(self)打印出来的就是一个 dict :
    self: {'email': '[email protected]', 'name': 'Test1', 'image': 'about:blank', 'passwd': '1234567890'}
    focusheart
        8
    focusheart  
       2016-11-01 10:24:49 +08:00
    https://github.com/hfutcbl/python-liaoxuefeng_practice/blob/master/aiohttpPractice/orm.py
    检查一下 orm.py 里对于 Model 类的构造:

    class Model(dict, metaclass=ModelMetaclass):

    def __init__(self, **kw):
    super(Model, self).__init__(**kw)

    相当于调用的 dict 的构造, dict 的构造里没有将 key 直接转为 instance property 的默认行为吧?不过 ModelMetaclass 的__new__ 里可以处理吧。
    另外,一般习惯上,对于这样使用 orm 的,用 instance[key] 的方式比较普遍吧。
    woshicai
        9
    woshicai  
    OP
       2016-11-01 11:41:04 +08:00
    @focusheart
    非常感谢回答, 终于明白 self.key 为什么不行了。在 ModelMetaclass 的 __new__函数里没有确实没有将 key 处理为 instance property 。
    但是还是有个问题:并不是所有 self.key 打印出来的值都是类中定义的 default 值,见输出:

    [email protected] <StringField, varchar(50):None> <StringField, varchar(50):None> <StringField, varchar(500):None>

    还有个问题:
    最初我是用 getattr(self, key, None) 来获取属性,
    class Model:
    ......
    def __getattr__(self, key):
    try:
    return self[key]
    print('-------\n getattr() called \n-------------')
    ......
    发现 getattr 每次运行只被调用一次(我期待调用次数和 key 的个数一样),想知道 getattr 的调用顺序。
    谢谢各位大神。
    slideclick
        10
    slideclick  
       2016-11-01 17:39:52 +08:00
    __getattr__(self, name)
    Called only when an attempt to retrieve the named attribute fails, after the obj,
    Class and its superclasses are searched. The expressions obj.no_such_attr, get
    attr(obj, 'no_such_attr') and hasattr(obj, 'no_such_attr') may trigger
    Class.__getattr__(obj, 'no_such_attr'), but only if an attribute by that name
    cannot be found in obj or in Class and its superclasses.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3445 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 04:40 PVG 12:40 LAX 21:40 JFK 00:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86