moonz
@moonz
web developer | seo | design

Возможно ли использовать setter без @property?

Собственно суть вопроса в заголовке:
Возможно ли без явного объявления @property, использовать декоратор @func.setter
Или в таких случаях единственным вариантом является описание geter с исключением, что бы продемонстрировать его недоступность?

Вариант с property в качестве атрибута property(None, func) работает как нужно, но хотелось бы и с декоратором тоже)

p.s Вот такой вариант меня не очень устраивает.
@property
def password(self):
    raise AttributeError('unreadable attribute')
    
@password.setter
def password(self, new_password):
    self.__password = new_password
  • Вопрос задан
  • 409 просмотров
Решения вопроса 1
Вариант через functools.partial
from functools import partial

writeonly_prop=partial(property, None)

class Test:
    @writeonly_prop
    def secret(self, val):
        self.__value = val

    def print_secret(self):
        print(self.__value)

    def __init__(self):
        self.__value = None

t = Test()
t.secret = 12
t.print_secret()
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
class Example:
    def x(self, value):
        self._x = value

    x = property(fset=x)

Ещё можно написать свой дескриптор или использовать метод __setattr__
Ответ написан
Комментировать
tumbler
@tumbler Куратор тега Python
бекенд-разработчик на python
class A:
    @field.setter  # NameError
    def field_setter(self, value):
        self.__field = value


На момент попытки выполнения field.setter в локальном контексте нет имени "field", поэтому воспользоваться задней половиной от property не получится. Но если вспомнить, что property - это фабрика дексрипторов, то можно подшаманить:

class setter:
    def __init__(self, name):
        self.name = name
    def __call__(self, setter_func):
        self.setter_func = setter_func
        return self
    def __get__(self, obj, type=None):
        return getattr(obj, f'_{obj.__class__.__name__}__{self.name}')
    def __set__(self, obj, value):
        self.setter_func(obj, value)

class A:
    @setter('field')
    def field_setter(self, value):
        self.__field = value

a = A()
a.field_setter = 1
b = a.field_setter
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы