I have a method that i have broken into smaller nested functions to break up the code base:
def foo(x,y):
def do_this(x,y):
pass
def do_that(x,y):
pass
do_this(x,y)
do_that(x,y)
return
Is there a way to run one of the nested functions by itself. eg:
foo.do_this(x,y)
EDIT:
I am trying to setup caching on a web server i have built using pyramid_breaker
def getThis(request):
def invalidate_data(getData,'long_term',search_term):
region_invalidate(getData,'long_term',search_term)
@cached_region('long_term')
def getData(search_term):
return response
search_term = request.matchdict['searchterm']
return getData(search_term)
This is my understanding may not be accurate:
Now the reason i have this is that the namespace used by the decorator to create the cache key is genereated from the function and the arguements. You can't therefore just put the decorator on getThis as the request variable is unique-ish and the cache is useless. So i created the inner function which has repeatable args (search_term).
However to invalidate the cache (ie refresh), the invalidation function requires scope to know of the 'getData' function so also needs to be nested. Therefore i need to call the nested function. You wonderful people have made it clear its not possible so is someone able to explain how i might do it with a different structure?
A function defined inside another function is called a nested function. Nested functions can access variables of the enclosing scope. In Python, these non-local variables are read-only by default and we must declare them explicitly as non-local (using nonlocal keyword) in order to modify them.
Inner functions, also known as nested functions, are functions that you define inside other functions. In Python, this kind of function has direct access to variables and names defined in the enclosing function.
The function1() will then go ahead and call function2() as it has been defined inside it. The code will return nothing when executed! The code returns the multiplication of the two numbers, that is, 10 and 5. The example shows that an inner function is able to access variables accessible in the outer function.
I assume do_this
and do_that
are actually dependent on some argument of foo
, since otherwise you could just move them out of foo
and call them directly.
I suggest reworking the whole thing as a class. Something like this:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def do_this(self):
pass
def do_that(self):
pass
def __call__(self):
self.do_this()
self.do_that()
foo = Foo(x, y)
foo()
foo.do_this()
These previous answers, telling you that you can not do this, are of course wrong. This is python, you can do almost anything you want using some magic code magic.
We can take the first constant out of foo's function code, this will be the do_this
function. We can then use this code to create a new function with it.
see https://docs.python.org/2/library/new.html for more info on new and https://docs.python.org/2/library/inspect.html for more info on how to get to internal code.
Warning: it's not because you CAN do this that you SHOULD do this, rethinking the way you have your functions structured is the way to go, but if you want a quick and dirty hack that will probably break in the future, here you go:
import new
myfoo = new.function(foo.func_code.co_consts[1],{})
myfoo(x,y) # hooray we have a new function that does what I want
UPDATE: in python3 you can use the types module with foo.__code__
:
import types
myfoo = types.FunctionType(foo.__code__.co_consts[1], {})
myfoo() # behaves like it is do_this()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: do_this() missing 2 required positional arguments: 'x' and 'y'
There is, you have to make them as an attribute of the function object. But this will work only after the first call of foo
.
def foo(x,y):
def do_this(x,y):
pass
def do_that(x,y):
pass
do_this(x,y)
do_that(x,y)
foo.do_this = do_this
foo.do_that = do_that
return
>>> foo.do_this(1, 2)
AttributeError: 'function' object has no attribute 'do_this'
>>> foo(1, 2)
>>> foo.do_this(1, 2)
>>>
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