Python中父类和子类间类属性(非实例属性)的设置获取的传递

前几天做一个项目,遇见类似这样一个问题。父类是个公用类,很多子项目中都运用到了,而子类也要作为一个基本类在该项目中的很多地方都要用到,但是的原始父类里面有些类属性(注意这里是类属性,不是实力属性)。在程序运行时候要进行重新设置。

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

来看一个例子:

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]
[‘a‘]

发现,如果使用

Father.mylist = [‘a‘]

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

我也尝试了用@preproty和@xxx.setter等修饰符,单独以及配合@classmethod修饰符来实现用Father.mylist的实现类属性的同步设置,但结果都失败了。其实可以继续使用Grandfather的类名加类属性及Grandfather来实现父类属性的设置但是,就感觉明明有了新父类,模块中交替使用这两个类名来设置类属性,确实有点不是太完美。

后来经过尝试找到了一个新的方法,就是使用类元metaclass,至于metaclass的内容,大家可以在网上找到相应的文章,这里介绍两种使用方法。

第一种:

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]
[‘a‘]
[‘a‘]

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

第二中方法,当然,也是在理解第一种方法之后,后来在读别的文章的时候发现了第二种方法。这里写出来方便大家理解。

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中类是可以动态在任意合法位置使用合法缩进创建的。其实两者方法的原理一样。但是我个人还是更喜欢第一种,代码更加简洁明快。

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

时间: 2024-10-12 20:08:16

Python中父类和子类间类属性(非实例属性)的设置获取的传递的相关文章

java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题

1 /* 2 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 3 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 4 */ 5 import static java.lang.System.out; 6 7 public class PersonDemo 8 { 9 public static void main(String[] args) 10 { 11 //*********测试父类与子类之间的循环调用的问

Python之路-面向对象&继承和多态&类属性和实例属性&类方法和静态方法

一.面向对象 编程方式 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强-" 什么是面向对象 面向对象就不像面向过程那样按照功能划分模块了,它所关注的是软件系统有哪些参与者,把这些参与者称为对象,找出这些软件系统的参与者也就是对象之后,分析这些对象有哪些特征.哪些行为,以及对象之间的关系,所以说面向对象的开发核心是对象 什么是类 面向对象编程的两个重要的概念:类和对象 类是

java中父类与子类的关系以及使用

java中父类与子类的关系以及使用 在java中规定:一个父类可以有多个子类,但是一个子类只能有一个父类.子类可以通过extends关键字来继承父类.做个比较通俗的比喻,就像一个父亲可以有多个亲孩子,但是一个孩子只能有一个亲生父亲. 1.继承以及重写:子类继承父类是对父类属性和方法的全面继承,同时子类在继承了父类的方法后,可对父类的方法进行重写. public class Son extends Fat{ private int b; private String h1; public void

python中的静态成员方法和类成员方法

Python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的: 1)静态方法无需传入self参数,类成员方法需传入代表本类的cls参数: 2)从第1条,静态方法是无法访问实例变量的,而类成员方法也同样无法访问实例变量,但可以访问类变量: 3)静态方法有点像函数工具库的作用,而类成员方法则更接近类似Java面向对象概念中的静态方法. 实现静态方法和类方法的两种方式 一.在Python 2.3及之前,用staticmethod和classmethod类型对象包装实现 例

python 面向对象六 类属性和实例属性

一.实例属性 Python是动态语言,根据类创建的实例可以任意绑定属性. 1 >>> class Student(object): 2 ... def __init__(self, name): 3 ... self.name = name # 每个实例必须的属性 4 ... 5 >>> s = Student('Jack') 6 >>> s.score = 90 # 任意绑定属性 7 >>> s.name 8 'Jack' 9 &g

python中类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法

类对象.类属性与实例对象.实例属性的区别 在Python中一切皆是对象,类是一个特殊的对象即类对象,描述类的属性称为类属性.类属性在内存中只有一份,在__init__外部定义. 通过类创建的对象称为实例对象,描述实例对象的属性称为实例属性.实例属性在各自对象的内存中都保存一份,在__init__方法内部定义. 实例方法.类方法.静态方法的区别 这三种方法都是保存在类的内存中,调用者不同. 实例方法由对象调用,至少一个self参数,self代表对象的引用. 类方法有类调用,至少一个cls参数,并且

Python:类属性,实例属性,私有属性与静态方法,类方法,实例方法

From: http://www.cnblogs.com/pengsixiong/p/4823473.html 属性分为实例属性与类属性 方法分为普通方法,类方法,静态方法 一:属性: 尽量把需要用户传入的属性作为实例属性,而把同类都一样的属性作为类属性.实例属性在每创造一个类是都会初始化一遍,不同的实例的实例属性可能不同,不同实例的类属性都相同.从而减少内存. 1:实例属性: 最好在__init__(self,...)中初始化 内部调用时都需要加上self. 外部调用时用instancenam

python学习-类属性和实例属性

#类属性和实例属性 class Tool(object): #类属性 total = 0 def __init__(self,new_name): #实例属性 self.name = new_name #类属性 Tool.total += 1 tool1 = Tool("a1") tool2 = Tool("a2") tool3 = Tool("a3") print(tool1.name) print(tool2.name) print(tool

python 类属性与实例属性

#__author__ = 'juzi_juzi' #类属性与实例属性 #1.无法通过类访问实例属性: #2.类属性归类所所有,但是所有实例都可访问: #3.如果存在相同名称的类属性与实例属性,实例访问的时候会优先使用实例属性,实例找不到该属性再找类属性: #4.实例修改了类属性值,但原类属性对应的值仍存在: class Test(): count = 3 # count 为类属性: def __init__(self,name,age): self.name = name #name ,age