python - 为什么 super(SubPerson, SubPerson).name.__set__(self, value) 在描述符中调用 GETTER。(不是二传手)
问题描述
我正在研究描述符的工作方式以及子类的扩展。然后我注意到,当我使用 Descriptor 时,与普通的父子扩展 getter/setter 相比 - 在 Descriptor 版本中:
super(SubPerson, SubPerson).name.__set__(self, value)
调用 GETTER,而不是 Setter。
最好通过示例来解释,请参阅下面的两个版本。用 super() 注释了指定的行。输出在每个部分下方注释。问题是为什么要调用getter?谢谢。
描述符:
# Code where super(SubPerson, SubPerson).name.__set__(self, value) CALLS GETTER!
# A descriptor - Checking if Attribute is of type String
class String:
def __init__(self, name):
print("Descriptor__init__")
self.name = name
def __get__(self, instance, cls):
print("Descriptor__get__")
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
print("Descriptor__set__")
if not isinstance(value, str):
raise TypeError('Expected a string')
instance.__dict__[self.name] = value
# A class with a descriptor
class Person:
name = String('name') # Class Variable - for a Descriptor
def __init__(self, name):
self.name = name
# Here we extend the Descriptor functionality with a property
class SubPerson(Person):
@property
def name(self):
# print('Getting name') # use case
print("Extended__get__") # debug
return super().name
@name.setter
def name(self, value):
# print('Setting name to', value) # use case
print("Extended__set__") # debug
super(SubPerson, SubPerson).name.__set__(self, value) # THIS CALLS THE "GETTER" OF A PARENT (DESCRIPTOR)
@name.deleter
def name(self):
print('Deleting name') # use case
print("Extended__delete__") # debug
super(SubPerson, SubPerson).name.__delete__(self)
if __name__ == '__main__':
b = SubPerson("Retko")
# Descriptor__init__
# Extended__set__
# Descriptor__get__
# Descriptor__set__
无描述符:
# Code where super(SubPerson, SubPerson).name.__set__(self, value) CALLS SETTER!
class Person:
def __init__(self, name):
print("Parent __init__")
self.name = name # this will call the Setter
# Getter function
@property
def name(self):
print("Parents Getter")
return self._name
# Setter function
@name.setter
def name(self, value):
print("Parent_Setter")
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')
print("Extended__get__") # debug
return super().name
@name.setter
def name(self, value):
# print('Setting name to', value)
print("Extended__set__") # debug
super(SubPerson, SubPerson).name.__set__(self, value) # THIS CALLS THE "SETTER" OF A PARENT
@name.deleter
def name(self):
# print('Deleting name')
print("Extended__delete__") # debug
super(SubPerson, SubPerson).name.__delete__(self)
if __name__ == '__main__':
s = SubPerson ( 'Guido' )
# Parent __init__
# Extended__set__
# Parent_Setter
谢谢。
解决方案
推荐阅读
- sql - 在编写具有多个连接的查询时遇到问题
- c - 正确使用 strcpy() 并避免 valgrind 中的读写大小错误
- gerrit - 在 Gerrit 中,如何将任意标签推送到非标准位置?
- c++ - 在 C++ 中做一个场景问题并且不确定如何进行布尔和 if 循环
- elixir - Ecto ILIKE 用于多个关键字?
- javascript - 如果在 3 秒内没有发生 keydown 事件,JavaScript 会显示文本?
- database - 如何将旧的 magento(2.1.5) 数据库迁移到新的 magento2.3.3
- python-3.x - 分段函数
- regex - 正面展望案例
- c++ - C++ 段错误,可重现的示例