python - 关于在子类中扩展属性的问题
问题描述
我正在阅读O Reilly Python Cookbook。
我对以下代码有疑问,与扩展子类中的属性有关:
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
@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)
我很困惑:
super(SubPerson, SubPerson).name.__set__(self, value)
使用 super(SubPerson,SubPerson) 似乎将方法作为类变量访问,为什么不能将方法作为实例变量访问?
另外,set和 @name.setter 是如何相互关联的?它们实际上不是同一件事吗?
同一行可以写成:
super(SubPerson, SubPerson).name.settr(self,value)
解决方案
这里有两个问题。
首先是关于super(SubPerson, SubPerson)
。访问作为类属性的实际属性对象只是一个技巧。这里想要的是Person.name
,因为一旦有了它,我们就可以使用属性的 setter 和 deleter 函数。super().name
任何实例类型访问的问题是它super()
不返回对象而是代理。并且代理上的属性名称只会授予对 getter 的访问权限。
后者大约@name.setter
。实际上property
作为初始装饰器定义name
为属性对象。属性的setter
属性也是一个装饰器,在其对象上设置 setter 函数并返回该对象。这意味着它只打算在类定义时使用。实际上@name.setter
bloc 大致等价于类定义后的如下代码:
def foo(self, value):
...
SubPerson.name = SubPerson.name.setter(foo)
您要使用的方法是fset
属性的属性。这意味着 setter 部分可以写成:
@name.setter
def name(self, value):
print('Setting name to', value)
super(SubPerson, SubPerson).name.fset(self, value)
推荐阅读
- qt - 有没有办法在 QPrintPreviewDialog 中返回当前查看的页面?
- google-cloud-platform - Terraform 在 terraform 之外手动更改自动缩放组/实例组
- ios - SwiftUI - 正确使用 @available() 和 #available
- r - 调整操作按钮的大小会导致闪亮仪表板中的标题错位
- python - 为什么这个脚本运行,然后说没有响应?
- debugging - 调试 Windows 10 内核驱动程序 TCP 问题
- python - '是否已安装 poppler 并在 PATH 中' - 在 android 中运行 pdf2Image 脚本
- django-admin - 使用 django-import-export 导入后如何获取导入对象的实例?
- regex - 使用正则表达式查找具有给定属性的嵌套 HTML 元素
- javascript - React 使 useState 初始值有条件