在 python 中使用 属性 的 getter

Use of property's getter in python

我正在查看属性,无法理解 getter 的用法。

代码:

class A:
    def __init__(self,p):
        self._p = p
    @property
    def p(self):
        return self._p
    @p.setter
    def p(self, value):
        self._p = value
    @p.getter
    def p(self):
        return self._p

所以,我做了以下事情

obj = A(10)
print(obj.p)

我得到以下输出:

10

所以,我想,调用@p.getter 并返回_q 的值。

但是,我试过没有@p.getter如下

class A:
    def __init__(self,p):
        self._p = p
    @property
    def p(self):
        return self._p
    @p.setter
    def p(self, value):
        self._p = value

并做了以下事情

obj = A(10)
print(obj.p)

然后我得到了以下输出:

10

所以,我想知道@p.getter 在这里的实际用途是什么,当@属性 它自己能够给我们 _q

的值时

如您所见,在这种情况下,它完全没用,因为您已经通过了 getter 此处

@property
def p(self):
    return self._p

但它至少对一些极端情况可能有用,例如为现有 属性 动态重新定义 getter。我不得不说我实际上从未有过这样的用例但是好吧......

如果您想在子class 中覆盖来自父class 的getter,@property.getter 装饰器会很有用。它允许您轻松地 "copy" 来自父 class 的 属性 并仅覆盖 getter,保持 setter 和删除器不变。

示例:

class Parent:
    @property
    def p(self):
        return 'parent'

    @p.setter
    def p(self, value):
        print('setting p to', value)

    @p.deleter
    def p(self):
        print('deleting p')

class Child(Parent):
    @Parent.p.getter
    def p(self):
        return 'child'

print(Parent().p)  # output: parent
print(Child().p)   # output: child
Child().p = 3      # output: setting p to 3
del Child().p      # output: deleting p

函数上的 @property 装饰器创建一个新的 property 对象并将装饰函数设置为 getter。所以在相同的class中,@p.getter装饰器不是很有用,没有。

但是,如果您想覆盖子class中的getter或仅重用[=49],装饰器非常有用=] 的 属性,但完全不同 class:

class Foo(object):
    @property
    def p(self):
        return self._p

    @p.setter
    def p(self, value):
        self._p = value

class Bar(Foo):
    @Foo.p.getter
    def p(self):
        return self._p + 10

或者通过将 属性 对象复制到不同的 class:

class NotASubclass(object):
    @Foo.p.getter
    def p(self):
        return self._p * 10

现在 Bar()NotASubclass 的 属性 p 有不同的 getter,但都重用了定义在属性 对于 Foo()

在这两种情况下,@p.getter 装饰器都会创建一个新的 property 实例来存储为 class 对象的属性,但是它们的 fset 属性都指向相同的单一功能对象,充当 setter。这就是为什么在任何一种情况下仅引用 @Foo.p.getter 就足够了;您只需要 class 命名空间中的单个 property 实例。

另见 How does the @property decorator work? and Python overriding getter without setter