【问题标题】:Use of property's getter in pythonpython中属性getter的使用
【发布时间】:2018-12-17 01:36:23
【问题描述】:

我正在研究属性,但无法理解 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 在这里的实际用途是什么,当@property 它自己能够给我们 _q 的值时

【问题讨论】:

标签: python properties getter-setter


【解决方案1】:

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

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

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

【讨论】:

  • 那么,p.getter 是不是经常使用?你是这么说的吗?
  • @InAFlash cf Aran-Fey 的回答比我的要好得多
【解决方案2】:

@property.getter 装饰器在您想在子类中覆盖父类的 getter 时会很有用。它允许您轻松地“复制”父类中的属性并仅覆盖 getter,保持 setter 和 deleter 不变。

例子:

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

【讨论】:

    【解决方案3】:

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

    但是,如果您想在子类中重写 getter,或者仅在不同的类上重用属性的 setter,则装饰器非常很有用:

    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 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 实例。

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

    【讨论】:

    • 谢谢,第二个例子很棒
    • 属性默认返回自己,因为在实际实现中def __get__(self, obj, objtype=None): if obj is None: return self if self.fget is None: raise AttributeError("unreadable attribute") return self.fget(obj),如果没有定义getter,它会返回自己。因为我能够得到_p的值,我对吗?
    • @InAFlash:不,如果未定义 getter,则会引发 AttributeError 异常。 obj 是要绑定的实例,如果是 None 则访问在类上。所以ClassObj.property_name给你属性对象本身(因为descriptor protocol然后调用ClassObj.__dict__['property_name'].__get__(None, ClassObj)),instance.property_name给你getter函数的结果(因为然后ClassObj.__dict__['property_name'].__get__(instance, ClassObj)被调用)。
    猜你喜欢
    • 1970-01-01
    • 2021-12-02
    • 2019-06-04
    • 1970-01-01
    • 2016-05-03
    • 2011-01-28
    • 2016-03-03
    • 2011-01-08
    相关资源
    最近更新 更多