首页 > 解决方案 > 为什么 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

谢谢。

标签: python

解决方案


推荐阅读