更改嵌套函数的装饰器中的值
Changing values in decorator for nested functions
我有一个类似的案例 -
flag = True
print "Before All things happened, flag is", flag
def decorator(*a):
def real_decorator(function):
def wrapper(*args, **kwargs):
global flag
flag = False
print "just in real decorator before function call i.e. before", function.__name__
print "flag is " , flag
function(*args, **kwargs)
print "In real decorator after function call i.e. after", function.__name__
flag = True
print "flag is ", flag
return wrapper
return real_decorator
@decorator()
def subtota():
print "in subtota"
print "flag is" , flag
@decorator()
def print_args(*args):
print "in print args"
for arg in args:
print arg
print "flag is ", flag
subtota()
print "we do want flag to be false here, after subtota"
print "but, flag is ", flag
print_args("bilbo", "baggins")
print "after All things happended flag is ", flag
输出为
Before All things happened, flag is True
just in real decorator before function call i.e. before print_args
flag is False
in print args
bilbo
baggins
flag is False
just in real decorator before function call i.e. before subtota
flag is False
in subtota
flag is False
In real decorator after function call i.e. after subtota
flag is True
we do want flag to be false here, after subtota
but, flag is True
In real decorator after function call i.e. after print_args
flag is True
after All things happended flag is True
在这里,我不想在 subtota()
之后更改标志的值,或者我们可以这样说,我们希望保持每个函数的行为彼此独立。
我们怎样才能做到这一点?
PS - 无法避免使用模块级全局变量 flag
。
编辑 - 期望的行为 -
只有在最上面的函数执行后,该标志才应该为假。
我有点不清楚你的目标是什么。
如果您需要跟踪每个函数的状态,您可以在装饰函数对象本身上设置一个标志:
def decorator(*a):
def real_decorator(function):
def wrapper(*args, **kwargs):
function.flag = False
function(*args, **kwargs)
function.flag = True
return wrapper
return real_decorator
您也可以在此处将其设置为 wrapper
以使标志在装饰版本上可用:
wrapper.flag = False
如果你只需要在进入和退出最外层装饰调用时切换标志,你可以使用一个单独的全局来计算你有多少级别;你也可以在 decorator
函数上设置它:
def decorator(*a):
decorator._depth = 0
def real_decorator(function):
def wrapper(*args, **kwargs):
global flag
if decorator._depth == 0: # entering outermost call
flag = False
decorator._depth += 1
function(*args, **kwargs)
decorator._depth -= 1
if decorator._depth == 0: # exiting outermost call
flag = True
return wrapper
return real_decorator
将标志的旧值保存在 wrapper 中,并恢复为它而不是 True
除了使用作用域为装饰器的变量外,我尝试使用以下方法-
def decorator(*a):
def real_decorator(function):
def wrapper(*args, **kwargs):
global flag
old_flag = flag
flag = False
function(*args, **kwargs)
flag = old_flag
return wrapper
return real_decorator
这看起来有点简单,而且工作得很好。
我有一个类似的案例 -
flag = True
print "Before All things happened, flag is", flag
def decorator(*a):
def real_decorator(function):
def wrapper(*args, **kwargs):
global flag
flag = False
print "just in real decorator before function call i.e. before", function.__name__
print "flag is " , flag
function(*args, **kwargs)
print "In real decorator after function call i.e. after", function.__name__
flag = True
print "flag is ", flag
return wrapper
return real_decorator
@decorator()
def subtota():
print "in subtota"
print "flag is" , flag
@decorator()
def print_args(*args):
print "in print args"
for arg in args:
print arg
print "flag is ", flag
subtota()
print "we do want flag to be false here, after subtota"
print "but, flag is ", flag
print_args("bilbo", "baggins")
print "after All things happended flag is ", flag
输出为
Before All things happened, flag is True
just in real decorator before function call i.e. before print_args
flag is False
in print args
bilbo
baggins
flag is False
just in real decorator before function call i.e. before subtota
flag is False
in subtota
flag is False
In real decorator after function call i.e. after subtota
flag is True
we do want flag to be false here, after subtota
but, flag is True
In real decorator after function call i.e. after print_args
flag is True
after All things happended flag is True
在这里,我不想在 subtota()
之后更改标志的值,或者我们可以这样说,我们希望保持每个函数的行为彼此独立。
我们怎样才能做到这一点?
PS - 无法避免使用模块级全局变量 flag
。
编辑 - 期望的行为 - 只有在最上面的函数执行后,该标志才应该为假。
我有点不清楚你的目标是什么。
如果您需要跟踪每个函数的状态,您可以在装饰函数对象本身上设置一个标志:
def decorator(*a):
def real_decorator(function):
def wrapper(*args, **kwargs):
function.flag = False
function(*args, **kwargs)
function.flag = True
return wrapper
return real_decorator
您也可以在此处将其设置为 wrapper
以使标志在装饰版本上可用:
wrapper.flag = False
如果你只需要在进入和退出最外层装饰调用时切换标志,你可以使用一个单独的全局来计算你有多少级别;你也可以在 decorator
函数上设置它:
def decorator(*a):
decorator._depth = 0
def real_decorator(function):
def wrapper(*args, **kwargs):
global flag
if decorator._depth == 0: # entering outermost call
flag = False
decorator._depth += 1
function(*args, **kwargs)
decorator._depth -= 1
if decorator._depth == 0: # exiting outermost call
flag = True
return wrapper
return real_decorator
将标志的旧值保存在 wrapper 中,并恢复为它而不是 True
除了使用作用域为装饰器的变量外,我尝试使用以下方法-
def decorator(*a):
def real_decorator(function):
def wrapper(*args, **kwargs):
global flag
old_flag = flag
flag = False
function(*args, **kwargs)
flag = old_flag
return wrapper
return real_decorator
这看起来有点简单,而且工作得很好。