Я хотел бы иметь функцию в объекте, который создает элемент определенного поведения. Аналогично использованию декоратора @property. Но без объявления функции getter и setter. Я хотел бы создать много членов пользовательского поведения с теми же функциями getter и setter. Однако этот пример не работает. Когда я его new_prop
член new_prop
является объектом свойства, а не членом. Как я могу достичь своей цели?
class MyClass():
def __init__(self):
self.new_prop("my_prop1")
self.new_prop("my_prop2")
self.new_prop("my_prop3")
def new_prop(self, name):
def getter(self):
this_prop = getattr(self, "_" + name)
if this_prop is None:
return "This is None!"
else:
return this_prop
def setter(self, value):
setattr(self, "_" + name, value)
setattr(self, name, property(getter, setter))
setattr(self, "_" + name, None)
if __name__ == "__main__":
my_class = MyClass()
print(type(my_class.my_prop1))
property
является дескриптором, и, как и все дескрипторы, он вызывается только при разрешении как атрибут класса - как вы обнаружили, когда он является атрибутом экземпляра, методы __get__
и __set__
не вызываются.
Если ваша цель состоит в том, чтобы избежать переписывания одних и тех же геттеров и сеттеров для свойств N, простым простым решением является написать собственный дескриптор:
class MyProp(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, cls):
if obj is None:
return self
value = getattr(obj, "_" + self.name)
if value is None:
return "This is None!"
else:
return value
def __set__(self, obj, value):
setattr(obj, "_" + self.name, value)
class Foo(object):
prop1 = MyProp("prop1")
prop2 = MyProp("prop2")
Обратите внимание, что свойство объявляется как атрибут класса. Поэтому вы должны установить его в классе, а не в экземпляре:
setattr(self.__class__, name, property(getter, setter))
Является ли это полезным, это еще один вопрос, особенно установка атрибута класса в __init__
для каждого экземпляра. Вам следует рассмотреть возможность внедрения собственного дескриптора вне класса, чтобы вы могли:
class MyClass():
my_prop1 = new_prop("my_prop1")
my_prop2 = new_prop("my_prop2")
my_prop3 = new_prop("my_prop3")
class
и как создаются объекты класса - в основном операторclass
выполняет все операторы на верхнем уровне блокclass
, собирает все имена, созданные в этом блоке, в dict, передает этот dict вtype()
и связывает полученный объект класса с именем класса во вложенном пространстве имен. Это означает, что класс еще не существует при выполненииprop1 = MyProp(...)
, поэтомуMyProp
не может получить к нему доступ.