了解@property装饰器和继承

时间:2016-02-09 11:12:21

标签: python python-3.x inheritance super

Python 3,以防它非常重要。

我正在尝试正确理解如何在使用@property时实现继承,并且我已经搜索过StackOverflow并阅读了类似的20个类似的问题,因为他们正在尝试的问题无济于事要解决的是微妙的不同。这是我用于测试的代码:

class Example:
    def __init__(self):
        self.__data = None

    @property
    def data(self):
        return self.__data

    @data.setter
    def data(self, data):
        self.__data = data


class Example2(Example):
    def __init__(self):
        super().__init__()

    @property
    def data(self):
        return super().data  # Works!

    @data.setter
    def data(self, data):
        data = '2' + data
        #Example.data = data   # Works, but I want to avoid using the parent name explicitly
        #super().data = data  # Raises AttributeError: 'super' object has no attribute 'data'
        #super().data.fset(self, data) # Raises AttributeError: 'NoneType' object has no attribute 'fset'
        #super(self.__class__, self.__class__).data = data  # Raises AttributeError: 'super' object has no attribute 'data'
        super(self.__class__, self.__class__).data.fset(self, data)  # Works!


a = Example2()
a.data = 'element a'
print(a.data)

我无法理解为什么super().dataExample2 getter中起作用,而不是在setter中起作用。我的意思是,为什么在setter中需要一个类绑定方法,但在getter中,一个实例绑定方法可以工作?

有谁可以请我解释或解释为什么我在我测试的五个不同电话中的三个中获得AttributeError

是的,我知道,我可以在setter中使用Example.data,但在getter中不需要这样做,并且a)如果可能的话,我宁愿不显式使用父类名,而b)我不理解吸气剂和二传手之间的不对称。

1 个答案:

答案 0 :(得分:0)

你应该这样做:

class Example:
    def __init__(self):
        self._data = None

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, data):
        self._data = data


class Example2(Example):
    def __init__(self):
        super().__init__()

    @Example.data.setter
    def data(self, data):
        data = '2' + data
        self._data = data


    a = Example2()
    a.data = 'element a'
    print(a.data)

您收到属性错误,因为该类没有数据属性,实例具有该属性。

如果要覆盖@property,请执行以下操作:

class Example:
def __init__(self):
    self._data = None

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, data):
        self._data = data


class Example2(Example):
    def __init__(self):
    super().__init__()

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, data):
        data = '2' + data
        self._data = data