Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python, confused in decorate and closure

I have some test code:

def num(num):
    def deco(func):
        def wrap(*args, **kwargs):
            inputed_num = num
            return func(*args, **kwargs)
        return wrap
    return deco


@num(5)
def test(a):
    return a + inputed_num

print test(1)

when run this code, I got an error shows that 'inputed_num' is not defined

My question is: In wrap function, is there not a closure that func can got 'inputed_num' ?

Anyway, If not, how should I do to got my aim: Initialize some value, and use this value directly in the main function.

Thinks.

like image 850
Yueyoum Avatar asked Dec 05 '22 14:12

Yueyoum


1 Answers

No, there isn't a closure like that. Functions can close over variables that are present in the surrounding lexical context, not in the calling context. In other words, if you actually write one function in another, then the inner one can have access to variables in the outer one:

def f():
    g = 2
    def f2():
        print g
    f2()

But functions never have access to variables inside the function that called them.

In general there isn't a way to do what you want, viz., set an arbitrary variable in a function from outside the function. The closest thing is you could use a global inputed_num in your decorator to assign inputed_num as a global variable. Then test would access the global value.

def num(num):
    def deco(func):
        def wrap(*args, **kwargs):
            global outsider
            outsider = num
            return func(*args, **kwargs)
        return wrap
    return deco
@num(5)
def test(a):
    print a+outsider

>>> test(2)
7

But of course the variable setting is then global, so multiple concurrent uses (e.g., recursion) wouldn't work. (Just for fun, you can also see here for a very arcane way to do this, but it is way too crazy to be useful in a real-world context.)

like image 140
BrenBarn Avatar answered Dec 20 '22 14:12

BrenBarn