Python 重写内部函数

Python 重写内部函数,python,function,oop,Python,Function,Oop,我知道如何覆盖方法: class Foo(object): def bar(self): return True def damn_monkeys(self): return False Foo.bar = damn_monkeys 有可能实现类似的功能吗 def foo(arg1): def bar(arg2): return 1 return bar(arg1) foo.bar = monkeys # doesn't

我知道如何覆盖方法:

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


def damn_monkeys(self):
    return False

Foo.bar = damn_monkeys
有可能实现类似的功能吗

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

foo.bar = monkeys  # doesn't work as bar obviously isn't an attribute
我已经找到了一些钩子(
func\u code
),但这些钩子似乎是专门为检查员准备的,摆弄它们似乎有点可疑

我还注意到函数有一个
\uuuuu init\uuuu
\uuu调用\uuuu
引用,但它们似乎指向
\uu内置\uu.\uu函数
对象。我没有进一步检查,但函数似乎也是对象(在python中读取所有内容都是对象是有意义的)。我假设函数已经是
\uuu函数
对象的实例,这就是为什么
foo.\uuu init\uuu
不会引发错误,但是调试器从未触及它

有没有办法在不复制或修补代码的情况下重写内部函数


编辑复制答案:

我认为这是不可能的

即使你做了这样的事情,它也不会起作用:

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!! 
产生此结果的原因是,即使函数是对象,甚至可以具有属性,函数对象的内容(即其本地名称空间)也会计算一次。您不能在事后更改它(也就是说,不将它包装到另一个函数中,这不是您要问的),因为它永远不会得到重新评估-除非您重新定义它。对于函数对象成为一级对象意味着什么,请查看以及,以获得一些额外的说明

任何对象实际上都是这样。考虑:

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

# test_class evaluation
test_class
test_class()
计算消息只打印一次,因为命名空间计算一次,就像对任何其他对象一样

现在,正如您在问题中所说,您可以使用
test\u class.inner=my\u func
覆盖
test\u类的
inner
方法。但是,可以这样做的原因首先是类对象
test\u class
type
的一个实例(与所有类一样),
type
对象自动将本地对象作为属性添加到父对象中,例如,对于上例中的
test\u class.internal
test\u class.class\u属性


函数对象不是这种情况,它们不是
类型的实例。必须向函数对象显式添加属性。但是,即使这样做,函数的名称空间也已计算,因此更新函数对象属性对函数的计算没有影响,如
test\u func
示例所示

除非调用外部函数,否则内部函数甚至不存在。并且仅在通话期间。看看这个关于函数中有一个静态变量的问题,然后修改计数器对内部函数的回答


您还可以使用其他定义的内部函数修改外部函数。

我认为您应该阅读更多有关名称空间的一般信息。如果项目有一个类型或另一个类型,则没有多大区别。为了实现它,python必须在名称空间中查找它。如果需要“重写”它,为什么不将它重新构造为非内部函数?请注意,您实际上可以为函数提供任意属性,因此您可以将
bar
转换为
foo.bar
@jornsharpe background info。代码实际上要长得多,在第三方软件包中,我无法这样更改它。那么,您可以提供一个不太抽象的示例吗?你到底想达到什么目的?嵌套函数的全部要点是,它只在函数内部需要,作为实现细节,其他代码都不需要关心,因此很难找到它。内部函数实际上是外部函数的局部变量。因此,您的问题相当于“我可以从函数外部更改函数局部变量吗?”。好吧,答案是:不,除非你愿意修改函数本身的字节码。