One method is to simply use a class. This allows you to place a
and b
in the scope of the class while f
can still access them.
custom class
class F:
def __init__(self):
self.a = 2
self.b = 3
def __call__(self, x):
return x * self.a + self.b
f = F()
f(1)
# returns:
5
If you don't like having to call the class constructor, you can override __new__
to essentially create a callable with internal stored variables. This is an antipattern though and not very pythonic.
custom callable
class f:
a = 2
b = 3
def __new__(cls, x):
return x * cls.a + cls.b
f(1)
# returns:
5
This approach is based on the answers provided in this thread, though scoped to the specific problem above. You can use a decorator to update the global variables available to the function while also storin a
and b
within a closure.
decorator with closure
from functools import wraps
def dec_ab(fn):
a = 2
b = 3
@wraps(fn)
def wrapper(*args, **kwargs):
# get global scope
global_scope = f.__globals__
# copy current values of variables
var_list = ['a', 'b']
current_vars = {}
for var in var_list:
if var in global_scope:
current_vars[var] = global_scope.get(var)
# update global scope
global_scope.update({'a': a, 'b': b})
try:
out = fn(*args, **kwargs)
finally:
# undo the changes to the global scope
for var in var_list:
global_scope.pop(var)
global_scope.update(current_vars)
return out
return wrapper
@dec_ab
def f(x):
"""hello world"""
return x * a + b
This preserves the functions signature and keeps a
and b
from being altered
f(1)
# returns:
5
a
# raises:
NameError: name 'a' is not defined
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…