Я хотел бы понять, как встроенный работает функция "имущество". Что меня смущает, что "имущество" также может быть использован в качестве декоратора, но он только принимает доводы при использовании в качестве встроенной функции, а не при использовании в качестве декоратора.
Это пример из документации:
class C(object):
def __init__(self):
self._x = None
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
собственность
'ы аргументы getx
, setx
, delxбыл
и док строку.
В коде ниже "имущество" используется в качестве оформителя. Объектом его является функция х
, но в коде выше нет места для функции объекта в аргументах.
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
И, как на X.сеттери
X.декораторы делетер создали?
Я запутался.
Свойства (функции)` возвращает специальный объект дескриптора:
>>> 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>
это копия старого объекта, но с одной из функций, заменить.
Помните, что @оформитель
синтаксис-это просто синтаксический сахар; синтаксис:
@property
def foo(self): return self._foo
на самом деле означает то же самое, что
def foo(self): return self._foo
foo = property(foo)
так что фу
функция заменяется имущества(фу), которые мы видели выше, является особым объектом. Затем, когда вы используете @фу.метод set()
, что вы делаете, называете это свойство().сеттер
я показал вам выше, который возвращает новый экземпляр объекта недвижимости, но на этот раз с функцией сеттер заменить оформлены способ.
Следующей последовательности создает полную собственность, с помощью этих методов декоратор.
Сначала мы создаем некоторые функции и свойства объекта только геттер:
>>> 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
Далее мы будем использовать.метод метода set()` чтобы добавить сеттер:
>>> prop = prop.setter(setter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is None
True
В прошлом мы добавляем делетер с .делетер()
метод:
>>> prop = prop.deleter(deleter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is deleter
True
Последнее, но не менее важно, собственность
объект выступает в качестве объект дескриптора, так и .__вам__()
, .__набор__()
и .__удалить__()
методы вклиниться в экземпляр атрибута получения, установки и удаления:
>>> class Foo: pass
...
>>> prop.__get__(Foo(), Foo)
Get!
>>> prop.__set__(Foo(), 'bar')
Set to 'bar'!
>>> prop.__delete__(Foo())
Delete!
В Методические указания дескриптора включает в себя чистом Python пример реализации в свойство ' ()
тип:
класс недвижимости: "и подражать PyProperty_Type() в объекты/descrobject.с помощью"
деф инит(самостоятельная, fget=нет, fset=нет, fdel=нет, док=нет): самовыдвижение.fget = fget самовыдвижение.fset = fset самовыдвижение.fdel = fdel если Док нет и fget нет ни у кого: док = fget.док По себе.формате doc = док
деф вам(самовыдвижение, объект, objtype=нет): если obj является none: вернуться самостоятельно если самостоятельно.fget нет: поднять AttributeError (на"нечитаемые атрибут и") вернуться самостоятельно.fget(объект)
деф набор(самовыдвижение, obj, значение): если самостоятельно.fset нет: поднять AttributeError("могут'т набор атрибутов и") самовыдвижение.fset(obj, значение)
деф удалить(самовыдвижение, объект): если самостоятельно.fdel нет: поднять AttributeError("могут't удалить атрибут и") самовыдвижение.fdel(объект)
деф геттер(самовыдвижение, fget): тип вернуться(самовыдвижение)(fget, самовывоз.fset, самовывоз.fdel, самовывоз.док)
деф сеттер(самовыдвижение, fset): тип вернуться(самовыдвижение)(самовыдвижение.fget, fset, самовывоз.fdel, самовывоз.док)
деф делетер(самовыдвижение, fdel): тип вернуться(самовыдвижение)(самовыдвижение.fget, самовывоз.fset, fdel, самовывоз.док)
Документации он's просто ярлык для создания свойств только для чтения. Так
@property
def x(self):
return self._x
эквивалентно
def getx(self):
return self._x
x = property(getx)
Вот минимальный пример того, как `@недвижимости может быть реализовано:
class Thing:
def __init__(self, my_word):
self._word = my_word
@property
def word(self):
return self._word
>>> print( Thing('ok').word )
'ok'
В противном случае "слово" остается метод вместо свойства.
class Thing:
def __init__(self, my_word):
self._word = my_word
def word(self):
return self._word
>>> print( Thing('ok').word() )
'ok'
Первая часть проста:
@property
def x(self): ...
такой же, как и
def x(self): ...
x = property(x)
Следующим шагом будет расширить эту собственность с сеттер и делетер. И это происходит с помощью соответствующих методов:
@x.setter
def x(self, value): ...
возвращает новый объект недвижимости, который наследует все от старого Х
плюс данного сеттер.
х.делетер
работает одинаково.
Это следующие:
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
Ниже Еще один пример о том, как `@недвижимости может помочь, когда нужно рефакторить код, который берется из здесь (я описываю только он ниже):
Представьте, что вы создали класс "деньги" такой:
class Money:
def __init__(self, dollars, cents):
self.dollars = dollars
self.cents = cents
и пользователь создает библиотеку в зависимости от этого класса, где он/она использует, например,
money = Money(27, 12)
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.
Теперь давайте'ы предположим, вы решили изменить свой класс "деньги" и избавиться от долларов
атрибуты копеек
, но вместо этого решили только отслеживать общее количество копеек:
class Money:
def __init__(self, dollars, cents):
self.total_cents = dollars * 100 + cents
Если вышеупомянутые пользователь пытается запустить его/ее библиотеке, как раньше
money = Money(27, 12)
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
это приведет к ошибке
AttributeError: 'деньги' объект не имеет атрибут 'долларов'
Это означает, что теперь каждый, кто рассчитывает на вашу оригинальную деньги
класса придется менять все строки кода, где доллары
и копеек
используются, который может быть очень больно... так, как можно было этого избежать? С помощью `@недвижимости!
Вот как:
class Money:
def __init__(self, dollars, cents):
self.total_cents = dollars * 100 + cents
# Getter and setter for dollars...
@property
def dollars(self):
return self.total_cents // 100
@dollars.setter
def dollars(self, new_dollars):
self.total_cents = 100 * new_dollars + self.cents
# And the getter and setter for cents.
@property
def cents(self):
return self.total_cents % 100
@cents.setter
def cents(self, new_cents):
self.total_cents = 100 * self.dollars + new_cents
когда мы сейчас называем из нашей библиотеки
money = Money(27, 12)
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.
он будет работать как ожидалось, и нам не пришлось менять ни строчки кода в нашей библиотеке! На самом деле, мы бы даже не знали, что в библиотеке мы зависим от изменен.
Кроме того, сеттер
отлично работает:
money.dollars += 2
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 12 cents.
money.cents += 10
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 22 cents.
Вы можете использовать @недвижимости
также в абстрактных классах, я даю минимальный пример here.
Я читаю все посты здесь и поняла, что нам может понадобиться реальный пример из жизни. Почему, собственно, у нас есть @недвижимости?
Итак, рассмотрим приложение флягу, где вы используете систему проверки подлинности.
Вы объявляете модель 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)
В этом коде мы'вэ-то "скрытые" и атрибут пароль
с помощью @ "имущество", которое запускает
AttributeError` утверждение, когда вы пытаетесь получить к нему доступ напрямую, в то время как мы использовали @недвижимости.сеттер установить функцию 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()
...
Пароль атрибут замечать, что приходит из формы регистрации, когда пользователь заполняет форму. Подтверждение пароля происходит на переднем конце С равно('пароль', сообщение='пароли должны совпадать')
(в случае, если вам интересно, но это'с другой темы, связанные колбу формы).
Я надеюсь, что этот пример будет полезен
Этот момент был снят многими людьми там, но здесь прямой смысл, который я искал. Это то, что я чувствую, важно начать с @декоратор собственность. например:-
class UtilityMixin():
@property
def get_config(self):
return "This is property"
Вызов функции на "get_config()" и будет работать.
util = UtilityMixin()
print(util.get_config)
Если вы заметили, я не использовал и" () на" скобки для вызова функции. Это элементарные вещи, которые я искал @оформитель собственность. Так что вы можете использовать вашу функцию как переменную.
Позвольте'ы начать с Python декораторы.
На Python декоратор-это функция, которая помогает добавить некоторые дополнительные функции в уже существующую функцию.
В Python все является объектом. Функции в Python являются объектами первого класса, что означает, что они могут ссылаться на переменную, добавил в списки, переданные в качестве аргументов в другую функцию и т. д.
Рассмотрим следующий фрагмент кода.
def decorator_func(fun):
def wrapper_func():
print("Wrapper function started")
fun()
print("Given function decorated")
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
def say_bye():
print("bye!!")
say_bye = decorator_func(say_bye)
say_bye()
# Output:
# Wrapper function started
# bye
# Given function decorated
Здесь, можно сказать, что функция декоратор модифицированных нашу функцию say_hello и добавили несколько дополнительных строк кода в нем.
Синтаксис Python для декоратора
def decorator_func(fun):
def wrapper_func():
print("Wrapper function started")
fun()
print("Given function decorated")
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
@decorator_func
def say_bye():
print("bye!!")
say_bye()
Позвольте's заключила все, чем в случае, но перед этим позвольте'поговорим о некоторых упс принципа.
Геттеры и сеттеры используются во многих объектно-ориентированных языков программирования для того чтобы обеспечить принцип инкапсуляции данных(рассматривается как объединение данных с методами, которые работают с этими данными.)
Эти методы, конечно, геттер для получения данных и сеттер для изменения данных.
Согласно этому принципу, атрибуты класса изготавливаются частная скрывать и защищать их от других код.
Ага, @недвижимости в основном для Python способ, чтобы использовать геттеры и сеттеры.
Python имеет большое понятие называется свойство, которое делает жизнь объектно-ориентированного программиста гораздо проще.
Давайте предположим, что вы решили сделать класс, который может хранить температуру в градусах Цельсия.
class Celsius:
def __init__(self, temperature = 0):
self.set_temperature(temperature)
def to_fahrenheit(self):
return (self.get_temperature() * 1.8) + 32
def get_temperature(self):
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
self._temperature = value
Рефакторинг кода, вот как мы могли бы достичь его собственность.
В Python, собственность ()-это встроенная функция, которая создает и возвращает объект недвижимого имущества.
Объект недвижимости имеет три метода, метода GET(), сеттер () и delete().
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value")
return self.temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self.temperature = value
temperature = property(get_temperature,set_temperature)
Здесь
temperature = property(get_temperature,set_temperature)
могли бы быть разбиты,
# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)
Следует Отметить:
Теперь вы можете получить доступ к значению температуры в письменной форме.
C = Celsius()
C.temperature
# instead of writing C.get_temperature()
Мы можем идти дальше и не определять имена get_temperature и set_temperature как они лишние и загрязнять пространство имен класса.
В подходящие для Python способ для решения вышеуказанных проблем является использование @недвижимости.
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
@property
def temperature(self):
print("Getting value")
return self.temperature
@temperature.setter
def temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self.temperature = value
Примечания -
Как вы можете видеть, код, безусловно, менее изящный.
Теперь давайте'поговорим о один реальный практический сцены.
Позвольте'говорят, что вы создали класс следующим образом:
class OurClass:
def __init__(self, a):
self.x = a
y = OurClass(10)
print(y.x)
Теперь давайте'ы также предположим, что наш класс стал популярным среди клиентов, и они начали использовать его в своих программах, они сделали все виды присвоения объекта.
И в один роковой день, доверенный клиент пришел к нам и предложил, что "Х" есть, чтобы быть значением между 0 и 1000, это действительно ужасный сценарий!
Благодаря свойствам он'ы проста: мы создаем версию собственность на "Х" и.
class OurClass:
def __init__(self,x):
self.x = x
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
Это здорово, это'т это: вы можете начать с самого простого мыслимые реализации, и вы можете позже перейти на версию собственность без того, чтобы изменить интерфейс! Так что свойства не просто замена для геттеров и сеттеров!
Вы можете проверить эту реализацию здесь
"имущество" - это класс, за @недвижимости
декоратор.
Вы всегда можете проверить это:
print(property) #<class 'property'>
Я переписал пример из справки(собственность), чтобы показать, что
@недвижимости` синтаксис
class C:
def __init__(self):
self._x=None
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
c = C()
c.x="a"
print(c.x)
функционально идентичного имущества () синтаксис:
class C:
def __init__(self):
self._x=None
def g(self):
return self._x
def s(self, v):
self._x = v
def d(self):
del self._x
prop = property(g,s,d)
c = C()
c.x="a"
print(c.x)
Нет никакой разницы, как мы используем свойство, как вы можете видеть.
@недвижимости
декоратор реализуется через "имущество" класса.Итак, вопрос в том, чтобы объяснить "имущество" класса немного. Эта линия:
prop = property(g,s,d)
Был инициализации. Мы можем переписать его так:
prop = property(fget=g,fset=s,fdel=d)
Смысл fget
, fset и fdel
:
| fget
| function to be used for getting an attribute value
| fset
| function to be used for setting an attribute value
| fdel
| function to be used for del'ing an attribute
| doc
| docstring
На следующем изображении показано тройняшки мы, от свойства класс`:
__вам__
, `набор " и " удалить там, чтобы быть переопределен]2. Это реализация шаблона дескриптор в Python.
В общем, дескриптор-это атрибут объекта с “привязкой поведения”, один атрибут, чей доступ был переопределен методами в протоколе дескрипторов.
Мы также можем использовать свойство сеттер
, добытчик
и Стиратель
методов, чтобы привязать функцию к имуществу. Проверьте следующий пример. Метод С2
класса С
будет установить свойство два раза.
class C:
def __init__(self):
self._x=None
def g(self):
return self._x
def s(self, x):
self._x = x
def d(self):
del self._x
def s2(self,x):
self._x=x+x
x=property(g)
x=x.setter(s)
x=x.deleter(d)
c = C()
c.x="a"
print(c.x) # outputs "a"
C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x) # outputs "aa"
Свойства могут быть объявлены двумя способами.
Вы можете взглянуть на несколько примеров я уже писал о свойства в Python.
Вот еще один пример:
##
## 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( объекта ), например, кроме Я'м через Х вместо... Я не'т инициализировать в инит - ... ну.. да, но он может быть удален, потому что X определяется как часть класса....
Вывод:
[ Test Class ] Set x = 1234
[ Test Class ] Get x = -1234
[ x ] -1234
и если я закомментируйте самостоятельно.х = 1234 в инит тут выход такой:
[ Test Class ] Get x = None
[ x ] None
и если я поставил поле _default = нет на _default = 0 в геттер функцию ( как все геттеры должны иметь значение по умолчанию, но это вовсе'т передает в собственность значения от того, что я'вэ видел, так что вы можете определить его здесь, и он на самом деле это'т плохо, потому что по умолчанию можно определить один раз и использовать его везде ) т. е. физ х( самовыдвижение, помощью _default = 0 ):
[ Test Class ] Get x = 0
[ x ] 0
Примечание: геттер логика есть просто значение будет манипулировать ею чтобы убедиться, что он манипулировал ею - же для печати заявления...
Примечание: Я'м использоваться для Lua и уметь динамически создавать 10+ помощники, когда я называю одну функцию и я сделал что-то подобное для Python без использования свойств и это работает до определенной степени, но, хотя функции создаются прежде, чем быть используемым, есть еще вопросы, порой их называют до того, как создал что странно, как это'Т закодированные таким образом... я предпочитаю гибкость Луа мета-таблиц и тот факт, что я могу использовать сеттеры / геттеры, а не по существу прямой доступ к переменной... мне нравится, как быстро некоторые вещи могут быть построены с Python, хотя, например, программ с графическим интерфейсом. хотя я шью не может быть возможным без большого количества дополнительных библиотек - если я кодирую его в аутохотки-AutoHotkey я могу напрямую получить доступ к DLL вызывает, что мне нужно, и то же самое можно сделать в Java, С#, C++ и многое другое - может быть, я не'т найти нужную вещь, но для этого проекта я могу переключиться из кожи питона..
Примечание: код выходного сигнала на этом форуме сломано - пришлось добавить пробелы в первой части кода для его работы - для копирования / вставки обеспечат вам преобразовать все пробелы на символы табуляции.... Я использую вкладки для Python, потому что в файле, который составляет 10000 строк размер может быть от 512 Кб до 1 МБ с пробелами и 100 до 200Кб с вкладками, который приравнивает к массовым разница для размер файла, и сокращение времени обработки...
Вкладки также может быть скорректирована для каждого пользователя - так что если вы предпочитаете 2 места по ширине, 4, 8 или все, что вы можете сделать, это означает, что он продуман для разработчиков зрение дефицита.
Примечание: все функции, определенные в классе разве'т правильно отступом из-за ошибки в программном обеспечении форума - обеспечить понизить его, если вы копировать / вставить
Одно замечание:
для меня, для Python 2.х, @недвижимости
ничего'т работу, как рекламируется, когда я'т наследовать от объект
:
class A():
pass
но работал когда:
class A(object):
pass
для Python 3, всегда работал.