Python类与对象技巧(2):拓展子类属性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shenziheng1/article/details/83964480

更多的时候,我们需要拓展父类中property的功能。

class Person:
    def __init__(self, name):
        self.name = name
    
    # Getter funtion
    @property
    def name(self):
        return self._name
        
    # Setter  function
    @name.setter
    def name(self, value):
        if not isinstance(value, str):
            raise TypeError('Expected a string')
        self._name = value

    #Deleter function
    @name.deleter
    def name(self):
        raise AttributeError("Can't delete attribute")

class SubPerson(Person):
    @property
    def name(self):
        print('Getting parent class name')
        return super().name
 
    @name.setter
    def name(self, value):
        print('Setting name to', value)
        super(SubPerson, SubPerson).name.__set__(self, value)

    @name.deleter
    def name(self):
        print('Deleting name')
        super(SubPerson, SubPerson).name.__delete__(self)

p = SubPerson('ziheng')
# >>> Setting name to ziheng
print(p.name)
# >>> Getting parent class name
#     ziheng
p.name = 'chunxu'        
# >>> Setting name to chunxu  

在子类中扩展一个property可能会引起很多不易察觉的问题。 因为property其实是 getter、setter 和 deleter 方法的集合,而不是单个方法。 因此,当扩展property的时候,需要先确定是否要重新定义所有方法还是只修改其中一个。 在该例子中,所有的property方法都被重新定义。 在每个方法中,使用了 super() 来调用父类的实现。

在 setter 函数中使用 super(SubPerson, SubPerson).name.__set__(self, value) 的语句是没有错的。 为了委托给之前定义的setter方法,需要将控制权传递给之前定义的name属性的 __set__() 方法。 不过,获取这个方法的唯一途径是使用类变量而不是实例变量来访问它。 这也是为什么要使用 super(SubPerson, SubPerson) 的原因。

如果只想重定义其中一个方法,那只使用 @property 本身是不够的

错误代码实例;

class SubPerson(Person):
    @property  # Doesn't work
    def name(self):
        print('Getting name')
        return super().name

s = SubPerson('ziheng')
# >>> Traceback (most recent call last):
#       File "<stdin>", line 1, in <module>
#       File "****.py", line 5, in __init__
#            self.name = name
#    AttributeError: can't set attribute

正确代码实例:

class SubPerson(Person):
    @Person.name.getter
    def name(self):
        print('Getting name')
        return super().name
s = SubPerson('ziheng')
print(s.name)
# >>> Getting name
#     'ziheng'

博文参考《python3-cookbook》

猜你喜欢

转载自blog.csdn.net/shenziheng1/article/details/83964480