Использование декоратора @property
@property
декоратор может быть использован для определения методов в классе , которые действуют как атрибуты. Одним из примеров, где это может быть полезно, является предоставление информации, которая может потребовать первоначального (дорогостоящего) поиска и простого поиска после этого.
Учитывая некоторый модуль foobar.py
:
class Foo(object):
def __init__(self):
self.__bar = None
@property
def bar(self):
if self.__bar is None:
self.__bar = some_expensive_lookup_operation()
return self.__bar
затем
from foobar import Foo
foo = Foo()
print(foo.bar) # Это займет некоторое время, так как
# bar после инициализации имеет значение None.
# 42
print(foo.bar) # Это намного быстрее, так как bar
# теперь имеет значение
# 42
Использование декоратора @property для свойств чтения-записи
Если вы хотите использовать @property
для реализации пользовательского поведения для установки и получения, использовать этот шаблон:
class Cash(object):
def __init__(self, value):
self.value = value
@property
def formatted(self):
return '${:.2f}'.format(self.value)
@formatted.setter
def formatted(self, new):
self.value = float(new[1:])
Чтобы использовать это:
wallet = Cash(2.50)
print(wallet.formatted)
# $2.50
print(wallet.value)
# 2.5
wallet.formatted = '$123.45'
print(wallet.formatted)
# $123.45
print(wallet.value)
# 123.45
Переопределение только метода получения, установки или удаления объекта свойства
При наследовании от класса со свойством, вы можете предоставить новую реализацию одного или несколько свойства getter
, setter
или deleter
функций, с помощью ссылки на объекте собственности на родительском классе:
class BaseClass(object):
@property
def foo(self):
return # some_calculated_value()
@foo.setter
def foo(self, value):
return # do_something_with_value(value)
class DerivedClass(BaseClass):
@BaseClass.foo.setter
def foo(self, value):
return # do_something_different_with_value(value)
Вы также можете добавить установщик или удалитель, если раньше его не было в базовом классе.
Использование свойств без декораторов
Хотя использование синтаксиса декоратора (с @) удобно, оно также немного скрыто. Вы можете использовать свойства напрямую, без декораторов. Следующий пример Python 3.x показывает это:
class A:
p = 1234
def getX (self):
return self._x
def setX (self, value):
self._x = value
def getY (self):
return self._y
def setY (self, value):
self._y = 1000 + value # Странно, но можно
def getY2 (self):
return self._y
def setY2 (self, value):
self._y = value
def getT (self):
return self._t
def setT (self, value):
self._t = value
def getU (self):
return self._u + 10000
def setU (self, value):
self._u = value - 5000
x, y, y2 = property (getX, setX), property (getY, setY), property (getY2, setY2)
t = property (getT, setT)
u = property (getU, setU)
A.q = 5678
class B:
def getZ (self):
return self.z_
def setZ (self, value):
self.z_ = value
z = property (getZ, setZ)
class C:
def __init__ (self):
self.offset = 1234
def getW (self):
return self.w_ + self.offset
def setW (self, value):
self.w_ = value - self.offset
w = property (getW, setW)
a1 = A()
a2 = A()
a1.y2 = 1000
a2.y2 = 2000
a1.x = 5
a1.y = 6
a2.x = 7
a2.y = 8
a1.t = 77
a1.u = 88
print(a1.x, a1.y, a1.y2)
# 5 6 1000
print(a2.x, a2.y, a2.y2)
# 7 8 2000
print(a1.p, a2.p, a1.q, a2.q)
# 1234 1234 5678 5678
print(a1.t, a1.u)
# 77 88
b = B()
c = C()
b.z = 100100
c.z = 200200
c.w = 300300
print(a1.x, b.z, c.z, c.w)
# 5 100100 200200 300300
c.w = 400400
c.z = 500500
b.z = 600600
print(a1.x, b.z, c.z, c.w)
# 5 600600 500500 400400