Python描述符与属性

Zev*_*ner 10 python properties descriptor

可能重复:
何时以及为什么我可以将描述符类的实例分配给Python中的类属性而不是使用属性?

我很困惑何时使用属性vs描述符.我读到属性是一个专门的描述符.

有人可以发布这是如何工作的吗?

mil*_*ose 14

您应该阅读关于实际描述符的文档.Cliff的Notes版本:描述符是一种低级机制,可以让您挂钩对象的被访问属性.属性是这个的高级应用; 也就是说,属性是使用描述符实现的.或者,更好的是,属性标准库中已经为您提供的描述符.

如果您需要一种简单的方法从读取的属性返回计算值,或者在属性写入上调用函数,请使用@property装饰器.描述符API更灵活,但不太方便,并且在这种情况下可以说是"过度杀伤"和非惯用语.它对更高级的用例很有用,比如实现绑定方法,静态和类方法; 例如,当您需要知道属性是通过类型对象还是类型的实例访问时.

  • @JoranBeasley并没有像完全没必要那样气馁.由于Python允许您覆盖属性访问,因此您可以决定在子类中需要它.如果需要计算属性,则使用getter是合适的.在Java/C#中,您需要预先决定是否要允许覆盖特定属性,并在类层次结构的顶部提供此属性.这就是普遍使用属性的常见原因:它是"以防万一"完成的. (3认同)

roo*_*oot 10

您可以阅读更多关于这两个位置.但是这里有一个简单的例子来自同一本书,试图解释解决什么本质上是同一个问题的差异.如您所见,使用属性的实现要简单得多.

我们可以通过多种方式利用Python的内部机制来获取和设置属性值.最容易访问的技术是使用属性函数来定义与属性名称关联的get,set和delete方法.属性函数为您构建描述符.一种稍微不易访问但更具可扩展性和可重用性的技术是自己定义描述符类.这使您具有相当大的灵活性 您可以通过创建定义get,set和delete方法的类来实现此目的,并将描述符类与属性名称相关联.

属性函数为我们提供了一种实现简单描述符的便捷方法,而无需定义单独的类.我们可以编写getter和setter方法函数,然后将这些函数绑定到属性名称,而不是创建完整的类定义.

描述符示例:

class Celsius( object ):
    def __init__( self, value=0.0 ):
        self.value= float(value)
    def __get__( self, instance, owner ):
        return self.value
    def __set__( self, instance, value ):
        self.value= float(value)

class Farenheit( object ):
    def __get__( self, instance, owner ):
        return instance.celsius * 9 / 5 + 32
    def __set__( self, instance, value ):
        instance.celsius= (float(value)-32) * 5 / 9

class Temperature( object ):
    celsius= Celsius()
    farenheit= Farenheit()
>>>
oven= Temperature()
>>>
oven.farenheit= 450
>>>
oven.celsius
232.22222222222223
>>>
oven.celsius= 175
>>>
oven.farenheit
347.0
Run Code Online (Sandbox Code Playgroud)

属性示例:

class Temperature( object ):
    def fget( self ):
        return self.celsius * 9 / 5 + 32
    def fset( self, value ):
        self.celsius= (float(value)-32) * 5 / 9
    farenheit= property( fget, fset )
    def cset( self, value ):
        self.cTemp= float(value)
    def cget( self ):
        return self.cTemp
    celsius= property( cget, cset, doc="Celsius temperature" )
>>>
oven= Temperature()
>>>
oven.farenheit= 450
>>>
oven.celsius
232.22222222222223
>>>
oven.celsius= 175
>>>
oven.farenheit
347.0
Run Code Online (Sandbox Code Playgroud)

  • 我相信你的描述符实现摄氏度是不正确的.你应该在`instance`而不是`self`上设置摄氏度; 如果您创建两个温度对象,它们将共享相同的摄氏度值. (13认同)