问题
I've quite a few functions that uses some global variables to hold an object to be reused throughout the library, e.g.:
from some.other.lib import Object1, Object2, Object3, Object4, Object5
def function1(input):
global _object1
try:
_object1
except NameError:
_object1 = Object1
return _object1.func1(input)
def function2(input):
global _object2
try:
_object2
except NameError:
_object2 = Object2
# Use function1 to do something to the input
return _object2.func2(function1(input))
def function3(input):
global _object3
try:
_object3
except NameError:
_object3 = Object3
# Use function1 to do something to the input.
return _object3.func3(function1(input))
def function4(input):
global _object4
try:
_object4
except NameError:
_object4 = Object4
return _object4.func4(input)
def function5(input):
global _object5
try:
_object5
except NameError:
_object5 = Object5
# Use function4 to do something to the input.
return _object5.func5(function4(input))
Is there a way to write a decorator such that the code to check the global variable doesn't need to be manually hardcoded for each of the function*
?
E.g. something like:
def exist_decorator(_object, _class):
try:
_object
except NameError:
_object = _class
return _object
So the actual class implementation for function4()
will look like:
def function4(input):
global _object4
exist_decorator(_object4, Object4)
return _object4.func4(input)
Is something like this syntactically possible in Python with decorators? If not, how else can I create a decorator/cache for checking global variable?
回答1:
I guess you just want to cache some values. For this the straight forward approach in decent Python without abusing any hidden feature is this:
cache = {}
def function1(input):
try:
object1 = cache['object1']
except KeyError:
object1 = cache['object1'] = Object1
return object1.func1(input)
And similar for the other functions.
You can also avoid using the still-global variable cache
by storing everything within your function object:
def function1(input):
try:
object1 = function1.object1
except AttributeError:
object1 = function1.object1 = Object1
return object1.func1(input)
This is possible because functions are arbitrary objects to which you can add attributes. But some might call this an abuse and unclean code. As always in such cases, discuss this with your team first and maybe add it to the list of used techniques for this team or project before using it.
I prefer using the hidden feature of mutable arguments:
def function(input, object1Cache=[None]):
if object1Cache[0] is None:
object1Cache[0] = Object1
return object1Cache[0].func1(input)
This works in Python because a list as a default value for a function parameter is still mutable and will keep its value.
And again, this might be considered unclean and an abuse, so discuss this with your team before using it and document in your project notes that this technique is used.
来源:https://stackoverflow.com/questions/43907083/creating-a-decorator-cache-for-checking-global-variable