Override Inner Function

I know how to override methods:

class Foo(object):
    def bar(self):
        return True


def damn_monkeys(self):
    return False

Foo.bar = damn_monkeys

      

Is it possible to achieve something similar with functions?

def foo(arg1):
    def bar(arg2):
        return 1
    return bar(arg1)

foo.bar = monkeys  # doesn't work as bar obviously isn't an attribute

      

I found a few hooks ( func_code

), but they seem to be purely for the inspector and seem pretty dubious to play with.

I also noticed that functions are referenced __init__

and __call__

, but they seem to point to an object __builtin__.__function

. I haven't tested it yet, but it looks like functions are objects too (which makes sense to read everything in python is an object). I assume the functions are already instances of the object __function

and therefore foo.__init__

does not throw an error, however it is never affected by the debugger.

Is there a way to override the inner function without copying or fixing the code?

edit the duplicate with the answer: Can you fix a * just * nested function with a closure, or repeat the entire outer function?

+3


source to share


2 answers


I do not think that's possible.

Even if you do something like this, it won't work:

def test_func():
    def inner():
        print("inner")
    test_func.inner = inner
    test_func.inner()

test_func()    # inner
test_func.inner()    # inner

def outer(): 
    print("outer")

test_func.inner = outer
test_func.inner()    # outer
# AH HA!! SUCCESS?
test_func()    # inner
# NOPE!! 

      

The reason for this result is that even though functions are objects and may even have attributes, the contents of the function object (that is, its local namespace) are evaluated by ONCE. You cannot change it after the fact (that is, without wrapping it in another function that you are not asking about), because it is never re-evaluated - unless you override it. Check out this famous question , as well as the last section of this article , for some additional clarification on what it means that object objects are first-class objects.

This is actually the case with any object. Consider:



class test_class(): 
    print("test_class evaluation")
    class_attribute = None
    def inner(self):
        print("inner")

# test_class evaluation
test_class
test_class()

      

The rating message is only printed once because the namespace is evaluated ONE, like any other object.

Now, as you said in your question, you can override a inner

class method test_class

using test_class.inner = my_func

. However, the reason you can do this test_class

is because the class object is an instance type

(like all classes) and objects type

automatically have local objects added to the parent object as attributes, like for test_class.inner

and test_class.class_attribute

in the example above.

This does not apply to function objects that are NOT instances type

. You must explicitly add attributes to function objects. However, even if you do, the function's namespace has already been evaluated, so updating the attribute of the function object does not affect the function's evaluation, as shown in the example test_func

.

0


source


Your inner function doesn't even exist unless the outer is called. And only during a call. Look at this question about having a static variable in a function, then change the answers from counter to your inner function.

What is the Python equivalent for static variables inside a function?



You can also change the external function with another defined internal function.

0


source







All Articles