Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Общие вопросы > разборки с декораторами


Автор: setq 7.11.2005, 20:20
разбирался с http://www.python.org/doc/2.4/whatsnew/node6.html. результатом "разборок" стал следующий код (взятый по приведённой ссылке и слегка модифицированный):

Код
def sig (*types) :
    def deco (f) :
        def wrap (*args) :
            assert len (args) == len (types)
            cond = [isinstance (a,t) for a,t in zip (args, types)]
            assert cond == filter (None, cond)
            return f (*args)
        return wrap
    return deco


функция sig написана специально чтобы быть декоратором. её назначение - объявлять типы параметров, принимаемых функцией. так что кто скучает по Си, можете теперь писать что-то вроде:

Код
@ sig (int, int)
def intsum (x,y) :
    return x+y


Код
>>> intsum (3,4)
7
>>> intsum (3.14,4)

Traceback (most recent call last):
  File "<pyshell#73>", line 1, in -toplevel-
    intsum (3.14,4)
  File "C:/Documents and Settings/mgurevich/Desktop/sig.py", line 6, in wrap
    assert cond == filter (None, cond)
AssertionError


с использованием sig внутри классов будут трудности, потому что в пределах объявления классы не знают своего имени.

Автор: setq 8.11.2005, 11:54
опередили (( http://www.python.org/peps/pep-0318.html

Автор: setq 14.11.2005, 15:42
ок. ещё один рецепт: описание функции как рекурсивной. вводит специальное имя __f__, ссылающееся на саму функцию. если Вы считаете, что такой подход безопаснее с точки зрения редактирования кода, можете его использовать.

описание декоратора:

Код
def rec(f):
    name = isinstance(f,basestring) and f or '__f__'
    def deco(fobj):
        fobj.func_globals.update ({name:fobj})
        return fobj
    if name == '__f__':
        return deco(f)
    else:
        return deco


ИСПОЛЬЗОВАНИЕ

Код
@rec
def abc(x):
    if x>0:
        print ':)'
        __f__(x-1)  # вместо abc(x-1)


или Вас не устраивает имя __f__, можно задать своё через параметр декоратора (второй вариант той же функции):

Код
@rec('myrecf')
def abc(x):
    if x>0:
        print ':)'
        myrecf(x-1)  # вместо abc(x-1)


вызов (как обычно):

Код
>>> abc(3)
:)
:)
:)
>>> 


если я чего-то не учёл или может тут есть ошибка, скажите мне.

Автор: Sardar 14.11.2005, 16:11
[offtop]
"Какой мозгодробильный язык..." мысли в слух... smile
[/offtop]

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)