我知道如何覆盖方法:
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?
答案 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_func
是test_class
的实例(与所有类一样),type
对象自动添加本地对象父对象作为属性,例如上例中的type
和test_class.inner
。
函数对象不是这种情况,它不是test_class.class_attribute
的实例。您必须向函数对象显式添加属性。但是,即使这样做,函数的命名空间也已经过评估,因此更新函数对象属性对函数的求值没有影响,如type
示例所示。
答案 1 :(得分:0)
除非调用外部函数,否则内部函数甚至不存在。只有在通话期间。看看这个关于在函数中有一个静态变量的问题,然后将答案从一个计数器修改为你的内部函数。
What is the Python equivalent of static variables inside a function?
您还可以使用不同的已定义内部函数修改外部函数。