2009-07-17 4 views
1

Почему это не работает? Как я могу заставить его работать? То есть, как я могу сделать gu доступным в моей украшенной функции?Определяющие функции в декораторе

def decorate(f): 
    def new_f(): 
     def gu(): 
      pass 
     f() 
    return new_f 

@decorate 
def fu(): 
    gu() 

fu() 

Должен ли я добавить gu в словарь определенных функций как-то? Или я могу добавить gu в локальное пространство имен f до его вызова?

ответ

0

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

import new 

def with_bar(func): 
    def bar(x): 
     return x + 1 
    f_globals = func.func_globals.copy() 
    f_globals['bar'] = bar 
    return new.function(func.func_code, f_globals, 
         func.func_name, func.func_defaults, func.func_closure) 

@with_bar 
def foo(x): 
    return bar(x) 

print foo(5) # prints 6 

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

1

гу является локальной new_f функции на, которая является локальной для декорировать функцию.

1

gu() определен только в пределах new_f(). Если вы не вернете его или не привяжите к нему new_f() или что-то еще, на него нельзя ссылаться извне new_f()

Я не знаю, что вы делаете, но эта схема кажется очень сложной. Возможно, вы можете найти менее сложное решение.

+0

Пример бессмысленен, но я пытаюсь привести простейший пример, чтобы проиллюстрировать проблему. Должно быть достаточно ясно, что я хочу делать. Я хочу определить функцию в определении декоратора для использования в украшенной функции. – Alex

+0

@Alex: Не могли бы вы дать описание проблемы более высокого уровня, которую вы пытаетесь решить? Может быть, тогда кто-то может предложить более чистое решение, используя совершенно другой подход. – Ber

2

Если вам нужно передать gu к fu вам нужно сделать, это явно параметрами:

def decorate(f): 
    def new_f(): 
     def gu(): 
      pass 
     f(gu) 
    return new_f 

@decorate 
def fu(gu): 
    gu() 

fu() 
+0

Не могу ли я добавить функцию gu в атрибут f, чтобы свести к минимуму нарушение фактического определения fu. Я имею в виду, что это цель декораторов или АОП; для выделения проблем. – Alex

+1

@Alex, если 'gu' - это отдельная концепция из' fu', почему вы называете это 'fu' вместо' new_f'? Если они действительно разделены, это еще более удобно, когда они не видны друг от друга. Не могли бы вы рассказать подробнее о своем вопросе? – lispmachine

0

Почему бы не сделать ваш декоратор не классом, а функцией? По-видимому, это возможно, поскольку я обнаружил, что просмотрел справку для встроенного property. (Раньше я думал, что вы можете просто применить декораторов к классам, а не то, что сами декораторы могут быть классами.)

(Конечно, gu должен быть методом класса или внутреннего класса.)