设为首页 收藏本站
查看: 3739|回复: 0

[经验分享] Python中父类和子类间类属性(非实例属性)的设置获取的传递

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-6-27 10:29:42 | 显示全部楼层 |阅读模式
前几天做一个项目,遇见类似这样一个问题。父类是个公用类,很多子项目中都运用到了,而子类也要作为一个基本类在该项目中的很多地方都要用到,但是的原始父类里面有些类属性(注意这里是类属性,不是实力属性)。在程序运行时候要进行重新设置。

背景:Python中父类的类属性,类方法,实力属性都能够被子类继承,实力属性的再设置很简单,当然为了控制类属性的访问权限(Python中不能完全实现控制),也可以用@preproty装饰符优化和控制实力属性的设置,父类的类属性被子类继承,可以很容易的获得父类属性的内容,但是如果想设置父类的类属性,就要用 父类名.类属性名 称来实现,那么能不能用 子类名.类属性名 来实现类属性的同步设置呢。

来看一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Grandfather(object):
    mylist = []

    def __init__(self):
        pass

class Father(Grandfather):


    def __init__(self):
        pass

Grandfather.mylist = [1, 2, 3, 4]
print Grandfather.mylist
print Father.mylist
Father.mylist = ['a']
print Grandfather.mylist
print Father.mylist




打印结果:
1
2
3
4
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
['a']



发现,如果使用
1
Father.mylist = ['a']



来实现类属性的设置,想象中,应该父类的类属性也能被重新设置,但是结果显示出,想象的和现实还是有差距的。

我也尝试了用@preproty和@xxx.setter等修饰符,单独以及配合@classmethod修饰符来实现用Father.mylist的实现类属性的同步设置,但结果都失败了。其实可以继续使用Grandfather的类名加类属性及Grandfather来实现父类属性的设置但是,就感觉明明有了新父类,模块中交替使用这两个类名来设置类属性,确实有点不是太完美。
后来经过尝试找到了一个新的方法,就是使用类元metaclass,至于metaclass的内容,大家可以在网上找到相应的文章,这里介绍两种使用方法。
第一种:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class MetaMyList(type):

    def _get_dummy(self):
        return Grandfather.mylist

    def _set_dummy(self, value):
        Grandfather.mylist = value

    mylist = property(_get_dummy, _set_dummy)

class Grandfather(object):
    mylist = []

    def __init__(self):
        pass

class Father(Grandfather):

    __metaclass__ = MetaMyList

    def __init__(self):
        pass

Grandfather.mylist = [1, 2, 3, 4]
print Grandfather.mylist
print Father.mylist
Father.mylist = ['a']
print Grandfather.mylist
print Father.mylist



打印结果令人很满意:
1
2
3
4
[1, 2, 3, 4]
[1, 2, 3, 4]
['a']
['a']



因为我们创建类的时候使用了__metaclass__, 那么类被创建的时候就会添加mylist作为自己的类属性,但是当我们使用Father.mylist来设置类属性的时候,我们其实是在将这个值传递给了Grandfather。因为Grandfather该类已经被创建,所以override该类属性的property是不现实(也许可以,但是我读书少)。那么只有在创建Father的时候来override此类属性的property,而如果想实现,那就必须用到类元,及metaclass,这东西简单,但是确实是所有类的始祖。

第二中方法,当然,也是在理解第一种方法之后,后来在读别的文章的时候发现了第二种方法。这里写出来方便大家理解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Grandfather(object):
    mylist = []
    def __init__(self):
        pass
class Father(Grandfather):
    class __metaclass__(type):
        @property
        def mylist(cls):
            return Grandfather.mylist
        @mylist.setter
        def mylist(cls, value):  # @NoSelf
            Grandfather.mylist = value
    def __init__(self):
        pass

Grandfather.mylist = [1, 2, 3, 4]
print Grandfather.mylist
print Father.mylist
Father.mylist = ['a']
print Grandfather.mylist
print Father.mylist




这里就很容易发现在python中类是可以动态在任意合法位置使用合法缩进创建的。其实两者方法的原理一样。但是我个人还是更喜欢第一种,代码更加简洁明快。

才疏学浅,欢迎交流提意见彼此提高。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-235910-1-1.html 上篇帖子: Python的argparse 模块处理参数 下篇帖子: XshellPortable,求大神帮忙解决下,我用XshellPortable这个软件连接的远程的租用的服
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表