Python装饰器可以访问装饰函数范围内的所有变量吗? e.g。
@decme
def call_me():
...
def caller_function():
context = context_creator()
call_me()
在这种情况下,decme
装饰者可以访问context
变量吗?
我们知道如果我们将call_me
作为参数传递,context
将能够访问context
,是否有办法将decme
传递给@decme(context)
函数?< / p>
请注意,call_me函数可以在单独的模块中定义,这意味着在我们调用call_me
函数时public class Second extends Activity{
TextView txtsrno,txtflower,txtstatus,txttimeleft;
ListView listView;
ArrayList<Model> flowerlist;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
txtsrno = (TextView) findViewById(R.id.srno);
txtflower = (TextView) findViewById(R.id.name);
txtstatus = (TextView) findViewById(R.id.buy);
txttimeleft=(TextView)findViewById(R.id.remtime);
listView = (ListView) findViewById(R.id.list);
flowerlist = new ArrayList<>();
flowerlist.add(new Model(1, "Rose",System.currentTimeMillis() + 1800000));
flowerlist.add(new Model(2, "Sunflower",System.currentTimeMillis() + 10000));
flowerlist.add(new Model(3, "Lotus",System.currentTimeMillis() + 30000));
flowerlist.add(new Model(4, "Jasmine",System.currentTimeMillis() + 600000));
SecondCustom sc = new SecondCustom(this, flowerlist);
listView.setAdapter(sc);
}
}
可能不正常
答案 0 :(得分:2)
@Alfe提供了一些特殊的解决方案。
你可能已经了解了跑步和跑步之间的时间安排。装饰器。
但是,由于您的目的不明确,根据您当前的代码,您可以尝试将代码重构为此样式:
def decme(context):
def real_decme(function):
def wrapper(*args, **kwargs):
function(*args, **kwargs)
return wrapper
return real_decme
def call_me():
pass
def caller_function():
context = context_creator()
decme(context)(call_me)()
在这种情况下,decme
可以处理上下文。但它不会在装饰器生成时间内运行。
答案 1 :(得分:0)
您可以访问调用者堆栈并查看其框架中的所有局部变量。我使用这种技术来实现我的Stack Environment in Python,它或多或少地使用了这种技术,顺便说一下,它可以更整齐地解决你的整体问题。
但是,除非你把它放到一个漂亮的图书馆,它隐藏了所有丑陋的细节,我称之为丑陋的黑客。
如何将此上下文传递到call_me()
?那么它的装饰师当然会收到它。
如果您选择使用StackEnv,这将是制定它的方法:
from stackEnv import stackEnv
def decme(function):
def wrapper(*args, **kwargs):
if stackEnv.context.someValue > someOtherValue:
doSomething()
return function(*args, **kwargs)
return wrapper
@decme
def call_me():
...
def caller_function():
stackEnv.context = context_creator()
call_me()
答案 2 :(得分:0)
函数是一个对象,可以有属性。您可以直接将上下文作为包装器的属性传递:
def decme(f):
def wrapped(*args, **kwargs):
# here we can access the context passed as wrapped.context
print("Before context:", wrapped.context)
cr = f(*args, **kwargs)
print("After")
return cr
wrapped.context = None
return wrapped
def caller_function():
# just pass the context
call_me.context = context_creator()
call_me()
此处原始call_me
没有context
属性的概念,但已修饰的函数具有。唯一的缺点是它是函数的一个属性,并且会在调用中持续存在。特别是它会在多线程环境中导致意外结果......
或者,您可以使用装饰器向可在运行时传递的函数添加一个附加参数。这种方式是线程安全的:
def decme(f):
def wrapped(context, *args, **kwargs):
# here we can access the context
print("Before context:", context)
cr = f(*args, **kwargs) # call the underlying function
print("After")
return cr
return wrapped
@decme
def call_me():
...
def caller_function():
# just pass the context
context = context_creator()
call_me(context)