Может ли декоратор, возвращающий необзываемое, принять дополнительные аргументы? - PullRequest
0 голосов
/ 15 мая 2018

Я вложил в подкласс встроенный класс property (назовите его SpecialProperty), чтобы добавить к нему больше полей:

class SpecialProperty(property):
    extra_field_1 = None
    extra_field_2 = None
    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        super().__init__(fget, fset, fdel, doc)

def make_special_property(func):
    prop = SerialisableProperty(fget=func)
    return prop

и я могу использовать его так же, как встроенный property() декоратор:

@my_module.make_special_property
def get_my_property(self): return self._my_property

Теперь я хочу дополнительно специализировать мои SpecialProperty экземпляры, заполняя одно из дополнительных полей, добавленных в класс, произвольным значением.

Возможно ли в Python написать декоратор, который будет возвращать свойство, также принимая дополнительные параметры?

Я бы хотел сделать это через декоратор, потому что именно здесь и когда информация наиболее актуальна, однако я застрял в ней. Я подозреваю, что это относится к области декораторов с аргументами , которые были хорошо документированы ( Декораторы с аргументами? (Переполнение стека) или Python Decorators II: Аргументы декоратора (artima .com) , чтобы привести только несколько источников), однако я не могу применить тот же шаблон к моему делу.

Вот как я пытаюсь это написать:

@my_module.make_special_property("example string")
def get_my_property(self): return self._my_property

А по классу объявив get_my_property:

>>> DeclaringClass.my_property
<SpecialProperty object at 0x...>
>>> DeclaringClass.my_property.extra_field_1
'example string'

Так как я делаю properties, декорированный член класса должен поменяться экземпляром SpecialProperty, и, следовательно, больше не должен вызываться - поэтому я не могу применить шаблон «вложенной оболочки» для разрешение декоратору с аргументами.

Неработающий пример:

def make_special_property(custom_arg_1):
    def wrapper(func):
        prop = SerialisableProperty(fget=func)
        prop.extra_field_1 = custom_arg_1
        return prop
    return wrapper # this returns a callable (function)

Мне не нужно возвращать вызываемый объект, если я хочу, чтобы свойство возвращало экземпляр SpecialProperty, но я не могу вызвать return wrapper(func) по понятным причинам.

1 Ответ

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

Ваш декоратор не возвращает вызываемое.Ваша фабрика декораторов возвращает декоратор, который возвращает свойство.Вы могли бы лучше понять, если переименовать функции:

def make_decorator(custom_arg_1):
    def decorator(func):
        prop = SerialisableProperty(fget=func)
        prop.extra_field_1 = custom_arg_1
        return prop
    return decorator

Когда вы декорируете с помощью make_decorator, он вызывается с аргументом, а decorator возвращается и вызывается для декорированной функции.

...