Рубрики
Без рубрики

Python Decorator с аргументами Python Decorator Учебник на примере

Комплексное учебное пособие на декоратор Python. Теги с Python, декоратор.

Если вы хотите по -настоящему глубоко погрузиться, вы должны прочитать это исчерпывающие статьи по Грэм Дамплтон Отказ Однако, если вы намереваетесь начать работу и улучшаться в чтении/написании декораторов Python, этой статьи должно быть достаточно.

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

[1]: def outer_function():
   ...:     print "1. This is outer function!"
   ...:     def inner_function():
   ...:         print "2. This is inner function, inside outer function!"
   ...:     print "3. This is outside inner function, inside outer function!"
   ...:     return inner_function()
   ...:

[2]: func_assign = outer_function()
1. This is outer function!
3. This is outside inner function, inside outer function!
2. This is inner function, inside outer function!

Отметьте в вышеупомянутом исполнении, как утверждение внутри внутренней функции напечатано на последнем, в последнюю среду, в котором возвращается Inner_Function, в конце Onlue_function, и выполнение можно увидеть во время назначения.

Decorator Python – это функция, которая получает функцию в качестве аргумента и возвращает другую функцию в качестве возвращаемого значения. Предположение для декоратора заключается в том, что мы будем передавать функцию в качестве аргумента, и подпись внутренней функции в декораторе должна соответствовать функции для украшения.

Функциональный декоратор

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

import time

def timetest(input_func):

    def timed(*args, **kwargs):

    start_time = time.time()
    result = input_func(*args, **kwargs)
    end_time = time.time()
    print "Method Name - {0}, Args - {1}, Kwargs - {2}, Execution Time - {3}".format(
        input_func.__name__,
        args,
        kwargs,
        end_time - start_time
    )
    return result
    return timed


@timetest
def foobar(*args, **kwargs):
    time.sleep(0.3)
    print "inside foobar"
    print args, kwargs

foobar(["hello, world"], foo=2, bar=5)

inside foobar
(['hello, world'],) {'foo': 2, 'bar': 5}
Method Name - foobar, Args - (['hello, world'],), Kwargs - {'foo': 2, 'bar': 5}, Execution Time - 0.30296087265

Мы передали функцию FOOBAR в декоратор по имени с наименованием. Внутренний декоратор, функция Foobar ссылается на переменную input_func. Результат, после выполнения Post of inprov_func называется результатом.

Приготовление @ к названию декоратора и написание то же самое над функцией вызывает декоратор и передает функцию декоратору (украшения).

Метод декоратор

Метод декораторы позволяют переопределить свойства класса, украшая, без необходимости найти функцию вызова.

def method_decorator(method):

    def inner(city_instance):
    if city_instance.name == "SFO":
        print "Its a cool place to live in."
    else:
        method(city_instance)
    return inner


class City(object):

    def __init__(self, name):
    self.name = name

    @method_decorator
    def print_test(self):
    print self.name

p1 = City("SFO")

p1.print_test()

Its a cool place to live in.

В приведенном выше фрагменте мы украсим метод класса Print_test. Метод_decorator печатает название города, если название экземпляра города не SFO.

Класс декораторы

Если вы хотите создать обратное возвращение другого вызова, подход декоратора функции проще. Если вы хотите, чтобы возвращение было функцией, декораторы функций должны быть предпочтительны, однако, если вы хотите, чтобы декоратор возвращал пользовательский объект, который делает что -то другое для того, что выполняет функция, в этом случае следует использовать декоратор класса.

С помощью класса вы можете добавить методы и свойства в украшенный вызовный объект или реализовать операции на них. Вы можете создавать дескрипторы, которые действуют специально, когда помещены в классы (E.g. ClassMethod, свойство)

class decoclass(object):

    def __init__(self, f):
    self.f = f

    def __call__(self, *args, **kwargs):
    # before f actions
    print 'decorator initialised'
    self.f(*args, **kwargs)
    print 'decorator terminated'
    # after f actions

@decoclass
def klass():
    print 'class'

klass()

Декораторы цепочки

Цепочка декоратора аналогична тому, как можно использовать множественное наследство для построения классов, мы можем написать столько декоратора, сколько хотим, и включить их один за другим в линию украшения с синтаксисом украшения, прежде чем определение функции будет украшено.

def makebold(f):
    return lambda: "" + f() + ""
def makeitalic(f):
    return lambda: "" + f() + ""

@makebold
@makeitalic
def say():
    return "Hello"

print say()

Одно следует иметь в виду, что порядок декораторов мы устанавливаем вопросы. Когда вы цепны декораторов, порядок, в котором они сложены, находится внизу.

Functools and Arps

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

def decorator(func):
    """decorator docstring"""
    def inner_function(*args, **kwargs):
    """inner function docstring """
    print func.__name__ + "was called"
    return func(*args, **kwargs)
    return inner_function


@decorator
def foobar(x):
    """foobar docstring"""
    return x**2

Если мы попробуем печатать имя и DOCSTRING, мы видим следующее

print foobar.__name__
print foobar.__doc__

inner_function
inner function docstring

Приведенное выше наблюдение заставляет нас сделать вывод, что функция Foobar заменяется inner_function. Это означает, что мы теряем информацию о функции, которая передается. functools.wraps приходит на нашу помощь. Он принимает функцию, используемую в декораторе, и добавляет функциональность копирования над названием функции, Docstring, Arguemnets и т. Д. Давайте украсить без потери информации:

from functools import wraps

def wrapped_decorator(func):
    """wrapped decorator docstring"""
    @wraps(func)
    def inner_function(*args, **kwargs):
    """inner function docstring """
    print func.__name__ + "was called"
    return func(*args, **kwargs)
    return inner_function


@wrapped_decorator
def foobar(x):
    """foobar docstring"""
    return x**2

print foobar.__name__
print foobar.__doc__

foobar
foobar docstring

Приведенная выше реализация сохраняет информацию о функции, передаваемой декоратору.

Как бы вы пошли о кэшировании информации внутри декоратора на основе класса?

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

Декораторы с аргументами

Функциональный декоратор с аргументами

from functools import wraps

def decorator(arg1, arg2):

    def inner_function(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print "Arguements passed to decorator %s and %s" % (arg1, arg2)
        function(*args, **kwargs)
    return wrapper
    return inner_function


@decorator("arg1", "arg2")
def print_args(*args):
    for arg in args:
    print arg

 print print_args(1, 2, 3)

 Arguements passed to decorator arg1 and arg2
 1
 2
 3

Декораторы на основе класса с аргументами

class ClassDecorator(object):

    def __init__(self, arg1, arg2):
    print "Arguements passed to decorator %s and %s" % (arg1, arg2)
    self.arg1 = arg1
    self.arg2 = arg2

    def __call__(self, foo, *args, **kwargs):

    def inner_func(*args, **kwargs):
        print "Args passed inside decorated function .%s and %s" % (self.arg1, self.arg2)
        return foo(*args, **kwargs)
    return inner_func


@ClassDecorator("arg1", "arg2")
def print_args(*args):
    for arg in args:
    print arg


 print_args(1, 2, 3)
 Arguements passed to decorator arg1 and arg2
 Args passed inside decorated function .arg1 and arg2
 1
 2
 3

Как бы вы пошли о внедрении декоратора с дополнительными аргументами?

Попробуйте следить за этим Так что пост Отказ

Возможно, вы захотите дальше исследовать Нанесение библиотеки Отказ

Статья первоначально появилась на Apcelent Tech Blog Отказ

Оригинал: “https://dev.to/apcelent/python-decorator-tutorial-with-example-529f”