我需要一种方法从外部代码块"注入"函数到函数中,因此它们可以在本地访问,并且它们不需要由函数的代码(定义为函数参数,从*args等等加载)专门处理.
简化的场景:提供一框架,使用户能够定义(用尽可能少的语法越好)自定义函数来操纵框架的其他对象(其是不必需global).
理想情况下,用户定义
def user_func():
Mouse.eat(Cheese)
if Cat.find(Mouse):
Cat.happy += 1
Run Code Online (Sandbox Code Playgroud)
在这里Cat,Mouse并且Cheese是框架对象,出于好的理由,它们不能限制在全局命名空间中.
我想为这个函数编写一个包装器,表现如下:
def framework_wrap(user_func):
# this is a framework internal and has name bindings to Cat, Mouse and Cheese
def f():
inject(user_func, {'Cat': Cat, 'Mouse': Mouse, 'Cheese': Cheese})
user_func()
return f
Run Code Online (Sandbox Code Playgroud)
然后,这个包装器可以应用于所有用户定义的函数(作为装饰器,由用户自己或自动,虽然我打算使用元类).
@framework_wrap
def user_func():
Run Code Online (Sandbox Code Playgroud)
我知道Python 3的nonlocal关键字,但我仍然认为丑陋(从框架的用户角度来看)添加额外的一行:
nonlocal Cat, Mouse, Cheese
Run Code Online (Sandbox Code Playgroud)
并担心将他需要的每个对象添加到此行.
任何建议都非常感谢.
假设我有这个功能:
def f(x,y):
return x+y
Run Code Online (Sandbox Code Playgroud)
如果我使用inspect.getargspec(f).args我得到['x','y']的结果.大.
现在假设我想g(a,b)在运行时创建另一个函数,我不知道参数名称a,b直到运行时:
def g(a,b):
return f(a,b)
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?Lambdas几乎是正确的,除了我只能在编译时分配参数名称.
g = lambda *p: f(*p)
Run Code Online (Sandbox Code Playgroud)
不知何故,我想在运行时基于列表L(例如L=['a','b'])动态创建函数,这样inspect.getargspec(g).args == L.
考虑以下:
def test(s):
globals()['a'] = s
sandbox = {'test': test}
py_str = 'test("Setting A")\nglobals()["b"] = "Setting B"'
eval(compile(py_str, '<string>', 'exec'), sandbox)
'a' in sandbox # returns False, !What I dont want!
'b' in sandbox # returns True, What I want
'a' in globals() # returns True, !What I dont want!
'b' in globals() # returns False, What I want
Run Code Online (Sandbox Code Playgroud)
我甚至不确定如何询问,但我希望函数的全局范围成为我打算运行它的环境,而不必在eval期间编译函数.这可能吗?
感谢您的任何意见
解
def test(s):
globals()['a'] = s
sandbox = {}
# create a new version of test() that uses the …Run Code Online (Sandbox Code Playgroud)