This small snippet came about as a result of this discussion on python-ideas, requesting a new syntax for dynamically reevaluating a function each time it is called.
This snippet implements a simple decorator to do so without added syntax.
#! /usr/bin/env python3frominspectimportgetsourcefromfunctoolsimportwraps# get the globals out of the waya,b,c=0,1,2defruntime(f):"""Evaluates the given function each time it is called."""# get the function's namename=f.__name__# and its source code, sans decoratorsource=remove_decorators(getsource(f))@wraps(f)defwrapped(*args,**kwargs):# execute the function's declarationexec(source)# since the above overwrites its name in the local# scope we can call it here using evalreturneval("%s(*%s, **%s)"%(name,args,kwargs))returnwrappeddefremove_decorators(source):"""Removes the decorators from the given function"""lines=source.splitlines()new_source='\n'.join((lineforlineinlinesifnotline.startswith('@')))returnnew_source@runtimedefexample1(x,y=[]):y.append(x)returny@runtimedefexample2(x=a**2+2*b+c):returnxif__name__=="__main__":print("Testing example1")print(example1(1))print(example1(2))print(example1(3))print()print("Testing example2 with default values")print(example2())print("Changing a to 5")a=5print(example2())
Sign in to comment