Заменить атрибут свойства обычным атрибутом - PullRequest
0 голосов
/ 28 мая 2018

Можно ли заменить свойство объекта атрибутом 'normal'?

Мне это нужно, потому что при первом обращении к атрибуту я хочу, чтобы значение было сгенерировано свойством.Но мне больше не нужно свойство потом:

class A(object):
    @property
    def x(self):
         self.x = "toto"   # Replace property, fail because no setter
         return self.x 

a = A()
print a.x # "toto"
a.x = "tata"

Я знаю, что могу сохранить значение во втором атрибуте, например _x, и проверить свойство, если _x существует, но я хочу знать, если оноВозможна замена самого свойства.

1 Ответ

0 голосов
/ 28 мая 2018

Чтобы обойти отсутствие установщика, вам придется напрямую манипулировать экземпляром __dict__ словаря.Однако вы не можете делать то, что хотите, с обычным property объектом, потому что это дескриптор данных .Доступ к атрибутам всегда дает приоритет дескриптора данных над атрибутами экземпляра.

Вместо этого вам придется создать собственный дескриптор, который не определяет __set__ или __delete__Метод:

class CachingProperty(object):
    def __init__(self, fget):
        self.name = fget.__name__
        self.fget = fget

    def __get__(self, instance, owner):
        if instance is None:
            return self
        value = self.fget(instance)
        instance.__dict__[self.name] = value
        return value

Этот дескриптор также заботится об установке значения непосредственно в атрибуте экземпляра __dict__, создавая таким образом атрибут экземпляра.

Используйте указанный выше класс вместо property:

class A(object):
    @CachingProperty
    def x(self):
         return "toto"

Демонстрация, показывающая, что метод получения вызывается только один раз:

>>> class Demo(object):
...     @CachingProperty
...     def foo(self):
...         print("Calling the foo property")
...         return "bar"
...
>>> d = Demo()
>>> d.foo
Calling the foo property
'bar'
>>> d.foo
'bar'
>>> vars(d)
{'foo': 'bar'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...