Получите экземпляр класса в качестве декоратора, когда класс/декоратор имеет аргументы и дополнительные методы.Python

Программы на Python
Ответить
Anonymous
 Получите экземпляр класса в качестве декоратора, когда класс/декоратор имеет аргументы и дополнительные методы.

Сообщение Anonymous »

В Python вы можете добавлять метаданные к функции как таковой:

Код: Выделить всё

def test(a,b):
return a+b

test.tags = ["test"]
test.version = "0.1"

print(test.tags) # ['test']
Дело в том, что я использую декоратор для регистрации своих функций на платформе оркестрации, которая поддерживает метаданные:

Код: Выделить всё

@orchestrator(
tags = ["test"],
version = "0.1"
)
def test1(a,b):
return a+b
Хотя некоторые части метаданных не передаются декоратору.
Я хотел создать класс, который позволит мне декорировать функция, которая применяет декоратор оркестратора и метаданные в качестве метода (и, возможно, впоследствии я захочу добавить некоторые методы).
Изначально я написал что-то вроде:

Код: Выделить всё

class step:

def __init__(self, function, version, description, tags):

self._function    = function
self._version     = version
self._description = description
self._tags        = tags

@orchestrator(
tags = self._tags,
version = self._version
)
def __call__(self):
return self._function

def metadata(self):
return {
"version": self._version,
"description": self._description,
"tags": self._tags,
}

# Other methods...

@step(
tags = ["test"],
description = "Example description"
version = "0.1"
)
def test(a,b):
return a+b
Конечно, у этого подхода есть несколько проблем:
  • Это не так, как класс как декоратор. определяется, если вам нужно передать аргументы классу:

    Код: Выделить всё

     # This:
    @step(
    tags = ["test"],
    description = "Example description"
    version = "0.1"
    )
    def test(a,b):
    return a+b
    # Is the same as this:
    step(tags = ["test"], description = "Example description", version = "0.1")(a,b)
    # So step is missing one arguments: function
    
  • Даже если бы это сработало, self._tags, self._version не были бы доступны оркестратору декоратор, если они находятся вне метода.
Итак, моя следующая попытка была:

Код: Выделить всё

class step:

def __init__(self, version, description, tags):

self._function    = None
self._version     = version
self._description = description
self._tags        = tags

def __call__(self,):

if not self._function:

@orchestrator(
tags=self._tags,
description=self._description
)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)

self._function = wrapper

return self._function

def metadata(self):
return {
"version": self._version,
"description": self._description,
"tags": self._tags,
}

# Other methods...

@step(
tags = ["test"],
description = "Example description"
version = "0.1"
)
def test(a,b):
return a+b
Это улучшение, поскольку:
  • Функция декорирована
  • Он правильно применяет декоратор оркестратора.
  • Функция декорирована и сохранена, поэтому она не декорируется каждый раз, когда я ее вызываю.
    Но это не позволяет мне для доступа к методам, поскольку test — это оформленный тест, а не экземпляр шаг.
Это позволяет мне получить доступ к метаданным с помощью print(test.version) и т. д.
Но я не могу добавлять методы, как я пытался с помощью test.metadata().
Некоторые функции можно обойти, написав:

Код: Выделить всё

class step:

def __init__(self, version, description, tags):

self._function    = None
self._version     = version
self._description = description
self._tags        = tags

def __call__(self,):

if not self._function:

@orchestrator(
tags=self._tags,
description=self._description
)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)

self._function = wrapper
self._function.version = self._version
self._function.description = self._description
self._function.tags = self._tags

return self._function

@step(
tags = ["test"],
description = "Example description"
version = "0.1"
)
def test(a,b):
return a+b
При использовании класса в качестве декоратора, принимающего аргументы, какой питонический способ получить экземпляр класса вместо метода .__call__()?

Подробнее здесь: https://stackoverflow.com/questions/793 ... nts-and-mo
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»