Декораторы с параметрами?

Вы могли использовать класс черт для этого. Что-то как:

#include <iostream>
using namespace std;

template <typename T> class type_name {
public:
    static const char *name;
};

#define DECLARE_TYPE_NAME(x) template<> const char *type_name<x>::name = #x;
#define GET_TYPE_NAME(x) (type_name<typeof(x)>::name)

DECLARE_TYPE_NAME(int);

int main()
{
    int a = 12;
    cout << GET_TYPE_NAME(a) << endl;
}

Эти DECLARE_TYPE_NAME определяют, существует для создания жизни легче в объявлении этого класса черт для всех типов, в которых Вы ожидаете нуждаться.

Это могло бы быть более полезно, чем решения, включающие typeid, потому что Вы добираетесь для управления выводом. Например, использование typeid для long long на моем компиляторе дает "x".

359
задан martineau 6 June 2017 в 07:45
поделиться

1 ответ

Известно, что следующие две части кода почти эквивалентны:

@dec
def foo():
    pass    foo = dec(foo)

############################################
foo = dec(foo)

частая ошибка А состоит в том, чтобы думать, что @ просто скрывает крайний левый аргумент.

@dec(1, 2, 3)
def foo():
    pass    
###########################################
foo = dec(foo, 1, 2, 3)

было бы намного легче записать декораторам, если вышеупомянутое - то, как @ работал. К сожалению, that’s не путь вещи сделаны.

<час>

Рассматривают декоратора Wait который haults выполнение программы в течение нескольких секунд. Если Вы не передаете во Время ожидания тогда, значение по умолчанию составляет 1 секунду. Примеры использования показывают ниже.

##################################################
@Wait
def print_something(something):
    print(something)

##################################################
@Wait(3)
def print_something_else(something_else):
    print(something_else)

##################################################
@Wait(delay=3)
def print_something_else(something_else):
    print(something_else)

, Когда Wait имеет аргумент, такой как [1 115], тогда вызов Wait(3) выполняется прежде , что-либо еще происходит.

таким образом, следующие две части кода эквивалентны

@Wait(3)
def print_something_else(something_else):
    print(something_else)

###############################################
return_value = Wait(3)
@return_value
def print_something_else(something_else):
    print(something_else)

, Это - проблема.

if `Wait` has no arguments:
    `Wait` is the decorator.
else: # `Wait` receives arguments
    `Wait` is not the decorator itself.
    Instead, `Wait` ***returns*** the decorator
<час>

Одно решение показывают ниже:

Позволяют нам начать путем создания следующего класса, DelayedDecorator:

class DelayedDecorator:
    def __init__(i, cls, *args, **kwargs):
        print("Delayed Decorator __init__", cls, args, kwargs)
        i._cls = cls
        i._args = args
        i._kwargs = kwargs
    def __call__(i, func):
        print("Delayed Decorator __call__", func)
        if not (callable(func)):
            import io
            with io.StringIO() as ss:
                print(
                    "If only one input, input must be callable",
                    "Instead, received:",
                    repr(func),
                    sep="\n",
                    file=ss
                )
                msg = ss.getvalue()
            raise TypeError(msg)
        return i._cls(func, *i._args, **i._kwargs)

Теперь мы можем записать вещи как:

 dec = DelayedDecorator(Wait, delay=4)
 @dec
 def delayed_print(something):
    print(something)

Примечание, что:

  • dec не не принимает несколько аргументов.
  • dec только принимает, что функция обертывается.

    импорт осматривают класс PolyArgDecoratorMeta (тип): определение вызов (Ожидают, *args, ** kwargs): попробуйте: arg_count = len (args), если (arg_count == 1): если вызываемый (args [0]): SuperClass = inspect.getmro (PolyArgDecoratorMeta) [1] r = SuperClass. вызов (Ожидают, args [0]), еще: r = DelayedDecorator (Ожидают, *args, ** kwargs), еще: r = DelayedDecorator (Ожидают, *args, ** kwargs), наконец: класс времени импорта r

    возврата передачи Ожидает (metaclass=PolyArgDecoratorMeta): определение init (я, func, задерживаюсь = 2): i. _ func = func i. _ задержка = задержка

    def __call__(i, *args, **kwargs):
        time.sleep(i._delay)
        r = i._func(*args, **kwargs)
        return r 
    

следующие две части кода эквивалентны:

@Wait
def print_something(something):
     print (something)

##################################################

def print_something(something):
    print(something)
print_something = Wait(print_something)

Мы можем распечатать "something" к консоли очень медленно, следующим образом:

print_something("something")

#################################################
@Wait(delay=1)
def print_something_else(something_else):
    print(something_else)

##################################################
def print_something_else(something_else):
    print(something_else)

dd = DelayedDecorator(Wait, delay=1)
print_something_else = dd(print_something_else)

##################################################

print_something_else("something")
<час>

Заключительные Примечания

Это может быть похожим на большое количество кода, но Вы не должны писать классы DelayedDecorator и PolyArgDecoratorMeta каждый раз. Единственный код, как который необходимо лично написать что-то следующим образом, которое довольно коротко:

from PolyArgDecoratorMeta import PolyArgDecoratorMeta
import time
class Wait(metaclass=PolyArgDecoratorMeta):
 def __init__(i, func, delay = 2):
     i._func = func
     i._delay = delay

 def __call__(i, *args, **kwargs):
     time.sleep(i._delay)
     r = i._func(*args, **kwargs)
     return r
0
ответ дан 23 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: