Python дескриптор против свойства
Возможный дубликат:
Когда и почему я могу назначить экземпляр класса дескриптора атрибуту класса в Python, а не использовать свойство?
Я не понимаю, когда использовать свойство против дескриптора. Я прочитал, что свойство является специализированным дескриптором.
Может кто-нибудь, пожалуйста, напишите, как это работает?
2 ответа
Вы должны прочитать документы о том, что дескрипторы на самом деле. Версия Cliff's Notes: дескрипторы - это низкоуровневый механизм, который позволяет вам подключаться к атрибутам объекта, к которому осуществляется доступ. Свойства являются приложением высокого уровня этого; то есть свойства реализуются с использованием дескрипторов. Или, что еще лучше, свойства - это дескрипторы, которые уже предоставлены вам в стандартной библиотеке.
Если вам нужен простой способ вернуть вычисленное значение из прочитанного атрибута или вызвать функцию при записи атрибута, используйте @property
декоратор. API дескриптора является более гибким, но менее удобным, и, возможно, "излишним" и не идиоматическим в этой ситуации. Это полезно для более сложных вариантов использования, таких как реализация связанных методов или статических методов и методов класса; когда вам нужно знать, например, был ли доступ к атрибуту через объект типа или экземпляр типа.
Вы можете прочитать больше об обоих отсюда. Но вот простой пример из той же книги, который пытается объяснить разницу, решая, что по сути является той же проблемой. Как видите, реализация с использованием свойств намного проще.
Есть несколько способов использовать внутренние механизмы Python для получения и установки значений атрибутов. Наиболее доступным методом является использование функции свойства для определения методов получения, установки и удаления, связанных с именем атрибута. Функция property создает для вас дескрипторы. Немного менее доступный, но более расширяемый и многократно используемый метод - это определение классов дескрипторов самостоятельно. Это дает вам значительную гибкость. Вы делаете это путем создания класса, который определяет методы get, set и delete, и вы связываете свой класс дескриптора с именем атрибута.
Функция свойства дает нам удобный способ реализовать простой дескриптор без определения отдельного класса. Вместо того, чтобы создавать полное определение класса, мы можем написать функции методов получения и установки, а затем связать эти функции с именем атрибута.
Пример дескриптора:
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