关于属性:在python中使用属性的getter

Use of property's getter in python

我正在研究属性,无法理解getter的用法。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
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

所以,我做了以下工作

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

我得到了以下输出:

10

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

但是,我尝试不使用@p.getter,如下所示

1
2
3
4
5
6
7
8
9
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

并做了以下工作

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

即使这样,我也得到了以下输出:

10

所以,我想知道@p.getter在这里的实际用途是什么,当@property it self能够为我们提供


如果要重写子类中父类的getter,则@property.getter修饰器可能很有用。它允许您轻松地从父类"复制"一个属性,并且只重写getter,保持setter和deleter的完整性。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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。所以在同一类中,@p.getter装饰器不是很有用,不是。

但是,如果您想要重写子类中的getter,或者只重用上的属性setter,但是在一个完全不同的类上,那么decorator非常有用:

1
2
3
4
5
6
7
8
9
10
11
12
13
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

或者通过将属性对象复制到其他类:

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

现在,Bar()NotASubclass的属性p具有不同的getter,但它们都重用在Foo()的属性上定义的setter。

在这两种情况下,@p.getter装饰器都创建了一个新的property实例来存储为类对象的属性,但它们的fset属性都指向同一个作为设置器的单函数对象。这就是为什么在这两种情况下只引用@Foo.p.getter就足够了;您只需要类命名空间中的单个property实例。

另请参见@property decorator如何工作?和python重写不带setter的getter


正如你所注意到的,在这种情况下,它是完全无用的,因为你已经通过了这里的getter。

1
2
3
@property
def p(self):
    return self._p

但它至少对一些角情况有用,比如动态地重新定义现有属性的getter。我不得不说实际上我从来没有过这样的用例,但是…