Украсьте методы экземпляра классом-декоратором, который заменяет метод экземпляром класса.Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Украсьте методы экземпляра классом-декоратором, который заменяет метод экземпляром класса.

Сообщение Anonymous »

Мне хотелось бы иметь возможность украшать методы экземпляра классом Step, чтобы методы заменялись объектом Step. В то же время я хотел бы иметь возможность создавать экземпляр шага с помощью Step(func, options).
Рабочий пример
Приведенный ниже пример, кажется, делает именно это, но я не уверен, что это более чистый способ достижения этой функциональности?

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

from typing import Callable
import functools

def step(options: "StepOptions" = None):
"""Step decorator"""
def decorator(func: Callable) -> Step:
return Step(func, options)
return decorator

class Step:
def __init__(self, func: Callable, options: "StepOptions" = None):
self.func = func
self.options = options if options else StepOptions()

def __get__(self, instance, owner=None):
# Creating a bound method by passing the instance to functools.partial
bound_method = functools.partial(self.func, instance)
functools.update_wrapper(bound_method, self.func)

# Return a new Step instance with the bound method
return Step(bound_method, self.options)

def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)

def __repr__(self):
return f"Step(func: {self.func.__name__}, options: {self.options})"

class StepOptions:

def __init__(self, retries: int = 0, timeout_s : float = None):
self.retries = retries
self.timeout_s = timeout_s

def __repr__(self):
return f"StepOptions(retries: {self.retries}, timeout_s: {self.timeout_s})"

class Test:
def __init__(self):
self.steps= [
Step(self.test_1, options=StepOptions(retries=3)),
self.test_2,
self.test_3,
]

self.value = 2

def test_1(self):
print("This is test_1")
return self.value

@step()
def test_2(self) -> str:
print("This is test_2")
return 20

@step(StepOptions(timeout_s=10))
def test_3(self) -> int:
print("This is test_3")
return 30

test = Test()

for test_step in test.steps:
print(f"type: {type(test_step)}")
print(test_step)
result = test_step()
print(result)
который выводит

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

type: 
Step(func: test_1, options: StepOptions(retries: 3, timeout_s: None))
This is test_1
2
type: 
Step(func: test_2, options: StepOptions(retries: 0, timeout_s: None))
This is test_2
20
type: 
Step(func: test_3, options: StepOptions(retries: 0, timeout_s: 10))
This is test_3
30
Альтернатива
В частности, я не уверен насчет метода __get__ Step. До сих пор я видел только примеры типа

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

    def __get__(self, instance, owner=None):
return functools.partial(self.__call__, instance)
Однако при этом print(test_2) приводит к результату

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

functools.partial(, )
вместо

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

Step(func: test_2, options: StepOptions(retries: 0, timeout_s: None))
Предыстория
Немного предыстории: я планирую использовать эту конструкцию в исполнителе тестов. Идея состоит в том, что, создавая экземпляр Step из каждой функции шага теста, у меня есть место для хранения метаданных (например, StepOptions) для каждого шага и доступа к этим метаданным в исполнителе теста. Если кто-то видит лучший способ сделать это, я буду более чем рад получить информацию!

Подробнее здесь: https://stackoverflow.com/questions/790 ... th-class-i
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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