覆盖内部功能

时间:2015-07-08 13:55:50

标签: 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 work as bar obviously isn't an attribute

我找到了一些钩子(func_code),但这些钩子似乎只是为了检查员而且看起来很可疑。“/ p>

我还注意到函数有__init____call__引用,但这些似乎指向__builtin__.__function对象。我还没有进一步检查,但似乎函数也是对象(这对读取python中的所有东西都是一个对象是有意义的)。我认为函数已经是__function对象的实例,这就是为什么foo.__init__不会引发错误,但调试器从未触及它。

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

修改重复,回答为:Can you patch *just* a nested function with closure, or must the whole outer function be repeated?

2 个答案:

答案 0 :(得分:0)

我不相信这是可能的。

即使你做这样的事情,它也行不通:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
    android:layout_height="256dp"
    android:layout_width="match_parent"
    app:contentScrim="?attr/colorPrimary"
    android:fitsSystemWindows="true"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginBottom="60dp">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax"/>
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_height="?attr/actionBarSize"
            android:layout_width="match_parent"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.widget.NestedScrollView>

这个结果的原因是即使函数是对象,甚至可以有属性,函数对象的内容(即它的本地命名空间)也会被评估为ONCE。事实之后你不能改变它(也就是说,没有将它包装在另一个函数中,这不是你要求的),因为它永远不会被重新评估 - 除非你重新定义它。查看this famous question 以及last section of this article,了解函数对象作为第一类对象的含义。

这实际上是任何对象的情况。考虑一下:

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!! 

评估消息只打印一次,因为命名空间是ONCE评估的,就像它与任何其他对象一样。

现在,正如您在问题中所述,您可以使用class test_class(): print("test_class evaluation") class_attribute = None def inner(self): print("inner") # test_class evaluation test_class test_class() 覆盖inner类的test_class方法。但是,您首先要执行此操作的原因是类对象test_class.inner = my_functest_class的实例(与所有类一样),type对象自动添加本地对象父对象作为属性,例如上例中的typetest_class.inner

函数对象不是这种情况,它不是test_class.class_attribute的实例。您必须向函数对象显式添加属性。但是,即使这样做,函数的命名空间也已经过评估,因此更新函数对象属性对函数的求值没有影响,如type示例所示。

答案 1 :(得分:0)

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

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

您还可以使用不同的已定义内部函数修改外部函数。

相关问题