I know when using Groovy closures, I can change the delegate on the closure so function calls made within the closure could be defined externally.
Can I do something similar in Python?
Specifically, if you take the following code:
def configure():
build()
def wrap(function):
def build():
print 'build'
function()
wrap(configure)
I'd like it to print 'build' (only making changes to wrap()).
Some notes:
I don't want to pass functions into configure() since there may be a large number of functions that can be called by configure().
I also don't want to define those globally, because, once again, there may be a large number of functions that can be called by configure() and I don't want to pollute the global namespace.
Whether or not is a good way to do this is debatable, but here's a solution that doesn't modify the global namespace.
def configure():
build()
def wrap(f):
import new
def build():
print 'build'
new.function(f.func_code, locals(), f.func_name, f.func_defaults, f.func_closure)()
wrap(configure)
I found it at How to modify the local namespace in python
This is doable without metaprogramming. Have configure take the build function as a parameter:
def default_build():
print "default build"
def configure(build_func=None):
build_func = build_func or default_build
build_func()
def wrap(func):
def build():
print "wrap build"
func(build)
wrap(configure)
This way makes it explicit that the behaviour of the configure function can change.
You can fiddle with the namespaces configure sees as well to do something more like what I understand Groovy does:
def build():
print "default build"
def configure():
build()
def wrap(func):
def _build():
print "wrap build"
old_build = func.func_globals['build']
func.func_globals['build'] = _build
func()
func.func_globals['build'] = old_build
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With