Декоратор на python — требуется объяснение

#python #decorator

#python #декоратор

Вопрос:

Я новичок в python и не могу понять концепцию декораторов. Я пытаюсь реализовать два декоратора: один, неотрицательный, который принимает произвольно длинный список целочисленных аргументов и выдает исключение, если какое-либо из них меньше 0, и другой, allCaps, который принимает произвольно длинный список строковых аргументов и использует их с большой буквы. Затем напишите простую функцию для тестирования каждого, оберните ее и продемонстрируйте, что каждый декоратор работает.

Я начал и дошел до этого момента.

 #!/usr/local/bin/python2.7

def NonNegative(inputs):
  for i in inputs:
    if i<0:
      raise exception

def allCaps(inputs2):
  for i in inputs2:
    a = i.upper()
    print a

def inputs
def inputs2():
  inputfile = open ("input.txt")
  sentence = inputfile.readlines()
  words = (sentence[0].split())
  return words

NonNegative(inputs)
  

Я был бы признателен, если кто-нибудь сможет объяснить мне концепцию декораторов. Я пытался понять это, но не смог.

Комментарии:

1. Это не декораторы. Декоратор оборачивает функции, возможно, возвращая новую функцию. Функции также украшены @foo

2. Ммм .. можете ли вы добавить образец декоратора с функциями?

3. что вы на самом деле пытаетесь здесь сделать, и почему вы думаете, что декораторы — это способ сделать это?

4. я просто пытаюсь узнать о декораторах

5. Я обнаружил, что лучшим описанием декораторов для тех, кто с ними не знаком, является это — оно поэтапно вводит вас в концепции. simeonfranklin.com/blog/2012/jul/1 /…

Ответ №1:

Подумайте о декораторе как о функции, которая оборачивает вашу функцию.

В математике у вас может быть функция f(x) . Если вы обернете его с помощью декоратора g , у вас есть g(f(x)) .

В python представление

 @function_g
def function_f():
    pass
  

Вот пример:

 def entryExit(f):
    def new_f():
        print "Entering", f.__name__
        f()
        print "Exited", f.__name__
    return new_f

@entryExit
def func1():
    print "inside func1()"
  

Вы видите, что мы определяем функцию extryExit , которая возвращает обернутую функцию (и, следовательно, принимает функцию в качестве входных данных). Он оборачивает эту функцию внутри new_f .

Оборачивая функцию декоратором, func1 преобразует из

 def func1():
    print "inside func1()"
  

Для

 def func1(f):
    print "Entering", f.__name__
    print "inside func1()"
    print "Exited", f.__name__
  

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

Вы можете прочитать больше о декораторах с этим превосходным вступлением здесь.

Ответ №2:

Вот пример подмножества того, что вы пытаетесь сделать:

 #!/usr/bin/env python


from __future__ import print_function


def nonnegative(f):
    def wrapper(xs):
        for x in xs:
            if x < 0:
                raise ValueError("{} < 0".format(x))
        return f(xs)
    return wrapper


@nonnegative
def inputs(xs):
    for x in xs:
        print(x)


inputs([1, 2, 3, 4])
inputs([-1])
  

Вывод:

 $ python foo.py 
1
2
3
4
Traceback (most recent call last):
  File "foo.py", line 23, in <module>
    inputs([-1])
  File "foo.py", line 11, in wrapper
    raise ValueError("{} < 0".format(x))
ValueError: -1 < 0
  

Смотрите: https://wiki .python.org/moin/PythonDecorators

PS: Я не совсем уверен, чего вы пытались достичь в allCaps качестве декоратора, поэтому я оставил это в покое, поскольку вы на самом деле его не использовали.

Комментарии:

1. Что делает эта строка — из будущего импорта print_function?

2. Привычка. Я обычно использую Python 2.x. from __future__ import print_function вводит новую print() функцию Python 3. В Python 2.x это был оператор / ключевое слово.

3. ОК. Я просто хотел сделать верхний регистр для набора входных данных. Я попробовал сделать это так же, как вы сделали это выше, но выдает ошибку — TypeError: объект ‘NoneType’ не вызывается. Невозможно отладить это.

4. Помните, что декораторы — это просто функции, которые обертывают другие функции, возможно, возвращая новые функции. Они принимают функцию в качестве входных данных.