Пример Отлично работает, НО нужно следующее, иначе вы получите err 5 (Незаконная процедура)
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Функция property()
возвращает специальный объект дескриптора :
>>> property()
<property object at 0x10ff07940>
Этот метод имеет дополнительные методы:
]>>> property().getter
<built-in method getter of property object at 0x10ff07998>
>>> property().setter
<built-in method setter of property object at 0x10ff07940>
>>> property().deleter
<built-in method deleter of property object at 0x10ff07998>
Они также действуют как декораторы . Они возвращают новый объект свойства:
>>> property().getter(None)
<property object at 0x10ff079f0>
, который является копией старого объекта, но с одной из замененных функций.
Помните, что синтаксис @decorator
просто синтаксический сахар; синтаксис:
@property
def foo(self): return self._foo
действительно означает то же, что и
def foo(self): return self._foo
foo = property(foo)
, поэтому foo
функция заменяется на property(foo)
, что мы видели выше, это специальный объект , Затем, когда вы используете @foo.setter()
, то, что вы делаете, вызывает метод property().setter
, который я показал вам выше, который возвращает новую копию свойства, но на этот раз с заменой функции setter на декорированный метод.
Следующая последовательность также создает свойство full-on, используя эти методы декоратора.
Сначала мы создаем некоторые функции и объект property
только с помощью getter:
>>> def getter(self): print 'Get!'
...
>>> def setter(self, value): print 'Set to {!r}!'.format(value)
...
>>> def deleter(self): print 'Delete!'
...
>>> prop = property(getter)
>>> prop.fget is getter
True
>>> prop.fset is None
True
>>> prop.fdel is None
True
Далее мы используем метод .setter()
для добавления сеттера:
>>> prop = prop.setter(setter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is None
True
В последний раз мы добавили дебетер с методом .deleter()
:
>>> prop = prop.deleter(deleter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is deleter
True
Последнее, но не более того, объект property
действует как объект дескриптора , поэтому он имеет .__get__()
, .__set__()
и .__delete__()
, чтобы подключиться к атрибуту получения, установки и удаления атрибута экземпляра:
>>> class Foo(object): pass
...
>>> prop.__get__(Foo(), Foo)
Get!
>>> prop.__set__(Foo(), 'bar')
Set to 'bar'!
>>> prop.__delete__(Foo())
Delete!
В дескрипторе Howto реализована реализация образца чистого python образца типа property()
:
class Property(object): "Emulate PyProperty_Type() in Objects/descrobject.c" def __init__(self, fget=None, fset=None, fdel=None, doc=None): self.fget = fget self.fset = fset self.fdel = fdel if doc is None and fget is not None: doc = fget.__doc__ self.__doc__ = doc 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) def __set__(self, obj, value): if self.fset is None: raise AttributeError("can't set attribute") self.fset(obj, value) def __delete__(self, obj): if self.fdel is None: raise AttributeError("can't delete attribute") self.fdel(obj) def getter(self, fget): return type(self)(fget, self.fset, self.fdel, self.__doc__) def setter(self, fset): return type(self)(self.fget, fset, self.fdel, self.__doc__) def deleter(self, fdel): return type(self)(self.fget, self.fset, fdel, self.__doc__)
Вот еще один пример:
##
## Python Properties Example
##
class GetterSetterExample( object ):
## Set the default value for x ( we reference it using self.x, set a value using self.x = value )
__x = None
##
## On Class Initialization - do something... if we want..
##
def __init__( self ):
## Set a value to __x through the getter / setter... Since __x is defined above, this doesn't need to be set...
self.x = 1234
return None
##
## Define x as a property, ie a getter - All getters should have a default value arg, so I added it - it will not be passed in when setting a value, so you need to set the default here so it will be used..
##
@property
def x( self, _default = None ):
## I added an optional default value argument as all getters should have this - set it to the default value you want to return...
_value = ( self.__x, _default )[ self.__x == None ]
## Debugging - so you can see the order the calls are made...
print( '[ Test Class ] Get x = ' + str( _value ) )
## Return the value - we are a getter afterall...
return _value
##
## Define the setter function for x...
##
@x.setter
def x( self, _value = None ):
## Debugging - so you can see the order the calls are made...
print( '[ Test Class ] Set x = ' + str( _value ) )
## This is to show the setter function works.... If the value is above 0, set it to a negative value... otherwise keep it as is ( 0 is the only non-negative number, it can't be negative or positive anyway )
if ( _value > 0 ):
self.__x = -_value
else:
self.__x = _value
##
## Define the deleter function for x...
##
@x.deleter
def x( self ):
## Unload the assignment / data for x
if ( self.__x != None ):
del self.__x
##
## To String / Output Function for the class - this will show the property value for each property we add...
##
def __str__( self ):
## Output the x property data...
print( '[ x ] ' + str( self.x ) )
## Return a new line - technically we should return a string so it can be printed where we want it, instead of printed early if _data = str( C( ) ) is used....
return '\n'
##
##
##
_test = GetterSetterExample( )
print( _test )
## For some reason the deleter isn't being called...
del _test.x
В принципе, то же, что и пример C (object), за исключением того, что я использую x вместо ... Я также не инициализирую __init - .. ну, но это можно удалить, потому что __x определен как часть класса ....
Выход:
[ Test Class ] Set x = 1234
[ Test Class ] Get x = -1234
[ x ] -1234
, и если я комментирую out self.x = 1234 в init, тогда выход будет:
[ Test Class ] Get x = None
[ x ] None
, и если я установил _default = None в _default = 0 в функции getter (поскольку все получатели должны иметь значение по умолчанию, но он не передается значениями свойств из того, что я видел, поэтому вы можете определить его здесь, и это на самом деле не плохо, потому что вы можете определить значение по умолчанию один раз и использовать его везде) ie: def x (self, _default = 0):
[ Test Class ] Get x = 0
[ x ] 0
Примечание. Логика-получатель просто должна управлять этим значением, чтобы гарантировать, что она управляется им - то же самое для операторов печати ...
Примечание. Я привык к Lua и могу динамически создавать 10+ помощников, когда я вызываю одну функцию, и я сделал что-то подобное для Python без использования свойств и работает до некоторой степени, но, несмотря на то, что функции создаются до их использования, по-прежнему возникают проблемы с тем, что они вызываются до их создания, что является странным, поскольку оно не кодируется таким образом. .. Я предпочитаю гибкость мета-таблиц Lua и факт, что я могу использовать фактические сеттеры / получатели вместо того, чтобы напрямую обращаться к переменной ... Мне нравится, как быстро некоторые вещи могут быть созданы с помощью Python, хотя, например, gui-программ. хотя я проектирую, может быть невозможен без большого количества дополнительных библиотек - если я его закодирую в AutoHotkey, я могу напрямую обращаться к нужным вызовам DLL, и то же самое можно сделать в Java, C #, C ++ и т. д. - возможно, я пока не нашли правильной вещи, но для этого проекта я могу переключиться с Python ..
Примечание: выход кода на этом форуме нарушен - мне пришлось добавить пробелы в первую часть кода для он работает - когда копирование / вставка гарантируют, что вы конвертируете все пробелы в вкладки .... Я использую вкладки для Python, потому что в файле, который составляет 10 000 строк, размер файла может быть от 512 КБ до 1 МБ с пробелами и от 100 до 200 КБ с вкладками, которые приравниваются к огромная разница в размере файла и сокращение времени обработки ...
Вкладки также могут быть скорректированы для каждого пользователя - поэтому, если вы предпочитаете ширину 2 пробела, 4, 8 или все, что вы можете сделать, это означает, что это вдумчивый для разработчиков с недостатками зрения.
Примечание. Все функции, определенные в классе, не имеют отступов должным образом из-за ошибки на форуме oftware - убедитесь, что вы вставляете его, если вы копируете / вставляете
Ниже приведен минимальный пример реализации @property
:
class Thing:
def __init__(self, my_word):
self._word = my_word
@property
def word(self):
return self._word
>>> print( Thing('ok').word )
'ok'
В противном случае word
остается вместо свойства.
class Thing:
def __init__(self, my_word):
self._word = my_word
def word(self):
return self._word
>>> print( Thing('ok').word() )
'ok'
self.word = my_word
- который тогда работал бы таким же образом print( Thing('ok').word ) = 'ok'
– SilverSlash
9 June 2017 в 04:41
Это следующее:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
То же, что и:
class C(object):
def __init__(self):
self._x = None
def _x_get(self):
return self._x
def _x_set(self, value):
self._x = value
def _x_del(self):
del self._x
x = property(_x_get, _x_set, _x_del,
"I'm the 'x' property.")
То же, что и:
class C(object):
def __init__(self):
self._x = None
def _x_get(self):
return self._x
def _x_set(self, value):
self._x = value
def _x_del(self):
del self._x
x = property(_x_get, doc="I'm the 'x' property.")
x = x.setter(_x_set)
x = x.deleter(_x_del)
То же, что и :
class C(object):
def __init__(self):
self._x = None
def _x_get(self):
return self._x
x = property(_x_get, doc="I'm the 'x' property.")
def _x_set(self, value):
self._x = value
x = x.setter(_x_set)
def _x_del(self):
del self._x
x = x.deleter(_x_del)
Это то же самое, что:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
Первая часть проста:
@property
def x(self): ...
совпадает с
def x(self): ...
x = property(x)
property
с помощью только геттера. Следующим шагом будет расширение этого свойства с помощью setter и deleter. И это происходит с помощью соответствующих методов:
@x.setter
def x(self, value): ...
возвращает новое свойство, которое наследует все, начиная с старого x
и заданного установщика.
x.deleter
работает одинаково .
Я прочитал все сообщения здесь и понял, что нам может понадобиться пример реальной жизни. Почему на самом деле у нас есть @property? Итак, рассмотрите приложение Flask, в котором вы используете систему аутентификации. Вы объявляете модель User в models.py
:
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
...
@property
def password(self):
raise AttributeError('password is not a readable attribute')
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
В этом коде у нас есть «скрытый» атрибут password
с помощью @property
, который запускает утверждение AttributeError
при попытке доступа к нему напрямую, в то время как мы использовали @ property.setter для установки фактической переменной экземпляра password_hash
.
Теперь в auth/views.py
мы можем создать экземпляр пользователя с помощью:
...
@auth.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm()
if form.validate_on_submit():
user = User(email=form.email.data,
username=form.username.data,
password=form.password.data)
db.session.add(user)
db.session.commit()
...
Атрибут уведомления password
, который поступает из регистрационной формы, когда пользователь заполняет форму. [3]
Надеюсь, что этот пример будет полезен
Свойство может быть объявлено двумя способами.
Вы можете взглянуть на несколько примеров, которые я написал о свойствах в python .
Документация говорит, что это просто ярлык для создания свойств readonly. Таким образом,
@property
def x(self):
return self._x
эквивалентно
def getx(self):
return self._x
x = property(getx)
Foo.prop = prop
вы можете сделатьFoo().prop = 5; pront Foo().prop; del Foo().prop
с желаемым результатом. – glglgl 27 June 2013 в 08:25type()
, поскольку доступ к атрибутам dunder и методам предназначен для использования в качестве точек расширения стандартными функциями и операторами. – Martijn Pieters♦ 10 March 2015 в 22:46@human.name.getter
изменил объектproperty
на месте вместо того, чтобы возвращать новое, атрибутhuman.name
будет изменен, изменив поведение этого суперкласса. – Martijn Pieters♦ 13 June 2015 в 14:33