1

I'm still trying to understand the basics of Python and am trying to figure out how to attach a value to y in the inner function action2.

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) 

Thanks

3
  • You can't because action always returns in the line before that. Commented Nov 23, 2014 at 1:07
  • 1
    In the third line, the function action returns x ** n, and everything after that on the same indentation level and below isn't ever executed. Also, is it intentional that you divide x by n without actually using the parameter y? Commented Nov 23, 2014 at 1:11
  • 2
    I suspect that your code is not properly formatted, should I be right could you please fix the code in your Q? Commented Nov 23, 2014 at 1:20

2 Answers 2

1

The usual reason for nesting functions like this is for function decoration. I asked a question a few months ago, and one of the answers seems to fit almost perfectly for your use case. Essentially you're trying to do this:

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

Which is a bit of a strange way to do

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

But we'll roll with it. In any case, let's return to our canonical function decorator and see how it compares.

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!

This is one layer too shallow for what you're trying to do. If we return back to the question I linked earlier on, we'll talk about a validator.

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'

Or more easily:

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

Since it's difficult to know EXACTLY what it is you're trying to do from your example code, hopefully this gives you a good leg to stand on when it comes to decorators and closures. Note that there's a whole world of things you have to do to make your functions introspectable, most of which can be taken care of by functools.wraps

Sign up to request clarification or add additional context in comments.

Comments

0

I assume you are trying to accomplish the following:

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

Now, your test commands give:

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

f is your outer “closure”, which is itself a “factory” function returning your inner closure.

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

You now have two completely independent functions f and g.

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

…and you can continue using f as before, which is probably not what you intended to do.

You can call the inner closure like this:

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

Or you can completely skip the variables:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.