我对何时使用属性与描述符感到困惑。我读到一个属性是一个专门的描述符。
有人可以发布这是如何工作的吗?
您应该阅读有关实际上是什么描述符的文档。Cliff's Notes 版本:描述符是一种低级机制,可让您连接到正在访问的对象的属性。属性是它的高级应用;也就是说,属性是使用描述符实现的。或者,更好的是,属性是标准库中已经为您提供的描述符。
如果您需要一种简单的方法来从属性读取中返回计算值,或者在属性写入时调用函数,请使用@property
装饰器。描述符 API 更灵活,但不太方便,并且在这种情况下可以说是“矫枉过正”且不习惯。它对于更高级的用例很有用,例如实现绑定方法或静态和类方法;例如,当您需要知道属性是通过类型对象还是类型的实例访问时。
您可以从此处阅读有关两者的更多信息。但这里有一个来自同一本书的简单例子,它试图解释解决本质上是同一个问题的区别。如您所见,使用属性的实现要简单得多。
有几种方法可以利用 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
属性示例:
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