2014-11-23 2 views
1

Я все еще пытаюсь понять основы Python и пытаюсь понять, как привязать значение к y во внутренней функции action2.Сложность Понимание вложенных функций в Python

def outer(n): 
def action(x): 
    return x ** n 
    def action2(y): 
     return x/n 
    return action2 
return action 

f = outer(2) #We are actually setting the n in action here 
print(f) 
print(f(5)) #We are now setting the x parameter in the inner function action 
print(f(4)) 

g = outer(3) 
print(g(3)) 

print(f(3) 

Благодаря

+0

Вы не можете, потому что 'action' всегда возвращается в строке до этого. –

+1

В третьей строке функция 'action' возвращает' x ** n', и все после этого на том же уровне отступа и ниже не выполняется. Кроме того, преднамеренно ли вы делите 'x' на' n', фактически не используя параметр 'y'? – user3426575

+2

Я подозреваю, что ваш код не отформатирован должным образом, должен ли я быть прав, не могли бы вы исправить код в своем Q? – gboffi

ответ

0

Я предполагаю, что вы пытаетесь сделать следующее:

def outer(n): 
    def action(x): 
     def action2(y): 
      return x ** n/y 
     return action2 
    return action 

Теперь ваши тестовые команды дают:

>>> f = outer(2) 
>>> print f 
<function action at 0x7f59b872e578> 
>>> print f(5) 
<function action2 at 0x7f59b872e5f0> 
>>> print f(4) 
<function action2 at 0x7f59b872e5f0> 

f ваш внешний «закрытие» , который сам по себе является «фабричной» функцией, возвращающей ваше внутреннее закрытие.

>>> g = outer(3) 
>>> print g(3) 
<function action2 at 0x7f59b872e668> 

Теперь у вас есть две совершенно независимые функции f и g.

>>> print f(3) 
<function action2 at 0x7f59b872e668> 

... и вы можете продолжать использовать f, как и раньше, что, вероятно, не то, что вы намеревались сделать.

Вы можете вызвать внутреннее замыкание так:

>>> f5 = f(5) 
>>> print f5(10.) 
2.5 

Или вы можете полностью пропустить переменные:

>>> outer(3)(10)(2) 
500 
1

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

def outer(n): 
    def action(x): 
     def action2(y): 
      return x**n/y 
     return action2 
    return action 

который является немного странным способом сделать

def action(n, x, y): 
    return x**n/y 

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

def decorator(func): 
    def wrapped(*args, **kwargs): 
     print("Calling inner function") 
     return func(*args, **kwargs) 
    return wrapped 

@decorator 
def foo(some_txt): 
    print("Hello, ", some_txt) 

# EXAMPLE OUTPUT 
>>> foo("World!") 
Calling inner function 
Hello, World! 

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

max_len_12 = lambda n: len(n) <= 12 # 12 character max field length 

def validation(v): 
    """ensures the result of func passes a validation defined by v""" 
    def outer(func): 
     def inner(*args, **kwargs): 
      while True: 
       result = func(*args, **kwargs) 
       # if validation passes 
       if v(result): 
        return result 
     return inner 
    return outer 

@validation(max_len_12) 
def valid_input(prompt): 
    return input(prompt) 

# EXAMPLE 
>>> valid_input("Enter your name (max 12 chars): ") 
Enter your name (max 12 chars): Adam YouBetYourAss Smith 
Enter your name (max 12 chars): Adam Smith 
'Adam Smith' 

Или проще:

valid_input = validation(max_len_12)(raw_input) 
# same as previous function 

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

Смежные вопросы