扩展子类的属性

子类继承父类的时候,可以继承并重写父类的property,如下所示:

class Person:
    def __init__(self, name):
        self.name = name

    # Getter function
    @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 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)

>>> s = SubPerson('Guido')
Setting name to Guido
>>> s.name
Getting name
'Guido'
>>> s.name = 'Larry'
Setting name to Larry
>>> s.name = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "example.py", line 16, in name
    raise TypeError('Expected a string')
TypeError: Expected a string
>>>

如果只想扩展property的某个方法,可以使用下面的代码:

class SubPerson(Person):
    @Person.name.getter
    def name(self):
        print('Getting name')
        return super().name

或者扩展setter方法:

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

在子类中扩展属性会引入许多非常细微的问题,这些问题与以下事实有关:将属性定义为getter,setter和deleter方法的集合,而不是单个方法。 因此,在扩展属性时,您需要确定是将所有方法一起重新定义还是仅重新定义其中一种方法。
在第一个示例中,所有property方法都一起重新定义。 在每个方法中,super()用于调用先前的实现。 在setter函数中使用super(Sub Person,SubPerson).name .__ set __(self,value)没错。 若要委托给setter的先前实现,控制需要通过先前定义的name property的__set __()方法传递。 但是,访问此的唯一方法是将其作为类变量而不是实例变量进行访问。 这就是super(SubPerson,SubPerson)操作的结果。

如果只想重新定义其中的某个方法,仅仅使用@property是不够的,如下:

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

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

而是可以使用下面的方式:

class SubPerson(Person):
    @Person.getter
    def name(self):
        print('Getting name')
        return super().name

>>> s = SubPerson('Guido')
>>> s.name
Getting name
'Guido'
>>> s.name = 'Larry'
>>> s.name
Getting name
'Larry'
>>> s.name = 42
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "example.py", line 16, in name
        raise TypeError('Expected a string')
TypeError: Expected a string
>>>

在此特定解决方案中,无法用更通用的名称替换硬编码的类名称Person。 如果不知道哪个基类定义了property,则应使用以下解决方案:重新定义所有property方法,并使用super()将控制权传递给先前的实现。

原文地址:https://www.cnblogs.com/jeffrey-yang/p/12044300.html

时间: 2024-11-02 12:07:30

扩展子类的属性的相关文章

重写UITableViewCell子类中属性的setter方法来实现隐藏或显示该cell中的某些控件

为什么会需要这样子的一种方法来实现隐藏或者显示一个cell中的某些控件呢? 其实,隐藏cell中某些控件可以直接在tableView:cellForRowAtIndexPath:方法中直接实现,我们需要判断外部变量比如bool值来决定是否显示这个控件,但需要额外的代码写在tableView:cellForRowAtIndexPath:方法当中,如果我们把bool值传递给该cell让其自己判断是否显示隐藏这个控件,可读性将会大幅增加:) 效果: 源码: YXCell.h // // YXCell.

自学前端开发:模拟Array功能 不是扩展子类

function MyArray(){};//创建模拟数组功能的构造函数 MyArray.prototype.length=0;//解决IE下使用扩展子类 数组length的bug (function(){ var methods=['push','pop','shift','unshift','slice','splice','join']; for(var i=0;i<methods.length;i++){ (function(name){ MyArray.prototype[name]=

转:zTree高级入门:如何通过扩展节点的属性来达到是否显示节点的删除编辑等图标(按钮)

当我们在使用ztree树组件的节点编辑功能时,只要我们引入了ztree相关节点编辑的js脚本文件: <script type="text/javascript" src=”/js/jquery.ztree.exedit-3.5.js"></script> 接着配置setting内的edit节点: var setting = { edit: { enable: true, showRenameBtn: true, showRemoveBtn: true

每日问题之子类字段属性使用父类的非静态字段属性错误

想在子类的字段.属性里调用父类的非静态字段.属性是不可行的,因为字段.属性的初始化是在类的构造函数之前. 比如子类调用父类的字段,需要初始化父类,但是父类没有初始化的时候你调用父类的字段.属性就会出错. class Son: Father { public string sonKey = "son" + base.fatherKye; public void sonMethod() { sonKey = "son" + base.fatherKye; } publi

Java基础之子类父类属性覆盖

当java的子类和父类具有相同名字的属性时,到底java是怎么处理的. 先看代码: package com.joyfulmath.study.field; public class Person { public String name; public String getName() { return name; } } package com.joyfulmath.study.field; public class Student extends Person { public String

子类的属性权限问题

父类: abstract class Shape{  public $name;  //形状的面积计算方法  abstract function area();  //形状的周长计算方法  abstract function circumference();  //形状的表单  abstract function view();  //形状的验证  abstract function check();    } 子类: class Rect extends Shape{  private $le

$.cssHooks 扩展 jquery 的属性操作

最近在研究 $.transit 然后发现了 $.cssHooks 这个方法,试了一下官方的 demo 表示好像并不是那么回事,所以决定深入的测试一下. $.cssHooks 的作用在于拓展属性(自己意淫的),比如用 "rotate" 代替 "transform: rotate()" 之类的,酱紫,$(".box1").css({"rotate":"10"}); 而且还可以用 "rotate&quo

扩展控件属性

1.创建用户控件项目 2.    注释以下这一行 private void InitializeComponent()        {            components = new System.ComponentModel.Container();            //this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;        } public partial class ExLabel : Lab

求解:为什么父类没有的属性,在强制转换成子类后却有值了

foreach (M912 m912 in m912List) { var m934 = (M934)m912; //强制转换后,父类M912 中没有的属性m918List在转换后的子类m934中能访问且有值 } 说明:其中M912 是父类M934 是子类 m918List是子类M934的一个属性 疑问,为什么父类没有的属性,在强制转换成子类后却有值了,这种情况是如何实现的? ************************************ 问题:将子类实例赋值给父类的实例后,子类对象所