嵌套函数是否存在等效的 override ?

2023-11-22

如果我有这个函数,我应该怎么做才能用我自己的自定义版本替换内部函数?

def foo():
    def bar():
        # I want to change this
        pass

    # here starts a long list of functions I want to keep unchanged
    def baz():
        pass

使用类可以很容易地覆盖该方法。不过,我不知道如何使用嵌套函数来做到这一点。改变foo成为一个类(或其他任何东西)不是一个选项,因为它来自我无法修改的给定导入模块。


这是一种方法,通过破解函数内部来创建一个新的 foo 来“做正确的事情”。 (正如@DSM提到的)。不幸的是我们不能直接跳入foo函数并弄乱其内部结构,因为它们大多被标记为只读,所以我们要做的就是修改我们手动构建的副本。

# Here's the original function
def foo():
  def bar():
    print("    In bar orig")
  def baz():
    print("  Calling bar from baz")
    bar()
  print("Foo calling bar:")
  bar()
  print("Foo calling baz:")
  baz()

# Here's using it
foo()

# Now lets override the bar function

import types

# This is our replacement function
def my_bar():
  print("   Woo hoo I'm the bar override")

# This creates a new code object used by our new foo function 
# based on the old foo functions code object.
foocode = types.CodeType(
    foo.func_code.co_argcount,
    foo.func_code.co_nlocals,
    foo.func_code.co_stacksize,
    foo.func_code.co_flags,
    foo.func_code.co_code,
    # This tuple is a new version of foo.func_code.co_consts
    # NOTE: Don't get this wrong or you will crash python.
    ( 
       foo.func_code.co_consts[0],
       my_bar.func_code,
       foo.func_code.co_consts[2],
       foo.func_code.co_consts[3],
       foo.func_code.co_consts[4]
    ),
    foo.func_code.co_names,
    foo.func_code.co_varnames,
    foo.func_code.co_filename,
    foo.func_code.co_name,
    foo.func_code.co_firstlineno,
    foo.func_code.co_lnotab,
    foo.func_code.co_freevars,
    foo.func_code.co_cellvars )

# This is the new function we're replacing foo with
# using our new code.
foo = types.FunctionType( foocode , {})

# Now use it
foo()

我很确定它不会捕获所有病例。但它适用于示例(对于我来说旧的 python 2.5.1 )

需要整理一下的丑陋的地方是:

  1. 传递给 CodeType 的巨大参数列表
  2. 丑陋的元组由co_consts仅覆盖一名成员。所有信息都在 co_consts 中,以确定要替换的信息 - 因此更智能的函数可以做到这一点。我用手挖了内部结构print( foo.func_code.co_consts ).

您可以找到一些有关CodeType and FunctionType通过使用解释器 命令help( types.CodeType ).

更新: 我认为这太丑了,所以我构建了一个辅助函数来使它更漂亮。使用助手你可以写:

# Use our function to get a new version of foo with "bar" replaced by mybar    
foo = monkey_patch_fn( foo, "bar", my_bar )

# Check it works
foo()

这是执行monkey_patch_fn:

# Returns a copy of original_fn with its internal function
# called name replaced with new_fn.
def monkey_patch_fn( original_fn, name, new_fn ):

  #Little helper function to pick out the correct constant
  def fix_consts(x):
    if x==None: return None
    try:
      if x.co_name == name:
        return new_fn.func_code
    except AttributeError, e:
        pass
    return x

  original_code = original_fn.func_code
  new_consts = tuple( map( fix_consts, original_code.co_consts ) )
  code_type_args = [
     "co_argcount", "co_nlocals", "co_stacksize", "co_flags", "co_code",
     "co_consts", "co_names", "co_varnames", "co_filename", "co_name",
     "co_firstlineno", "co_lnotab", "co_freevars", "co_cellvars" ]

  new_code = types.CodeType(
     *[ ( getattr(original_code,x) if x!="co_consts" else new_consts )
        for x in code_type_args ] )
  return types.FunctionType( new_code, {} )
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套函数是否存在等效的 override ? 的相关文章

随机推荐

  • 如何从 Windows 卸载 mongodb

    我看到一个教程说要运行这个 C mongodb bin mongod exe config C mongodb mongod conf remove 但该命令不起作用 因为没有mongod conf文件位于我的 Windows 中的 mon
  • Eclipse CVS 变更列表

    有没有办法查看 eclipse 项目中所有最近更改的文件 包括其他 CVS 用户最近更改的文件 谢谢 这里还有一个 Eclipse 变更日志插件 http code google com a eclipselabs org p change
  • svn 签出时“网络连接意外关闭”

    当我尝试结账时 svn checkout svn ssh serveradmin email protected home 87292 data svn repository trunk 我收到这个 无用的 错误 svn 网络连接意外关闭
  • pycharm 中的“预期语句结束”[重复]

    这个问题在这里已经有答案了 为什么我会收到此错误 请参阅 linting 说 预计声明结束 在pycharm中 我对 python 很陌生 尝试在 Python3 中使用括号进行打印 即print x 代替print x
  • 在间隔列表中搜索间隔重叠?

    假设 a b 表示从 a 到 b 的实线上的区间 a 给定一个间隔列表 x1 y1 x2 y2 找到与 x y 重叠的所有此类间隔的最有效方法是什么 显然 我可以尝试每一个并在 O n 内得到它 但我想知道是否可以以某种巧妙的方式对间隔列表
  • 错误:(59, 8) 错误:无法访问 android.support.v4.app.ActivityCompatApi23 的 ActivityCompatApi23 类文件。

    这是我的 build gradle apply plugin com android application android compileSdkVersion 25 buildToolsVersion 26 0 2 android con
  • 如何使用 SelectionModel 以编程方式选择材质树节点?

    我有一棵带有复选框的树 我们在这里使用 Material 的例子 我希望开始检查水果节点 如何检查这些节点 我看到SelectionModel has a select 示例传递节点的方法 但在示例中 构成树的数据是一个数组TodoItem
  • Android 中的屏幕亮度值

    如何获取活动的当前屏幕亮度 以下方法可以很好地通过调用将亮度设置为最大setBrightness 100 private void setBrightness int brightness WindowManager LayoutParam
  • 如何在 Windows Azure 辅助角色中安排任务

    我运行一个简单的 Azure Worker 角色 每天中午 12 点执行一项任务 下面是完成此操作的代码 public override void Run try while true int time Convert ToInt32 Da
  • Keydown 哪个不工作 Chrome 扩展

    我一直在为谷歌扩展的想法而苦苦挣扎 而你一如既往地是我最后的希望 好吧 我想单击 chrome 扩展上的按钮 这将导致页面扩展上的 keydown 模拟正在运行 我认为 chrome 在我的想法上有一些安全问题 它会阻止键盘模拟 使事件 i
  • 如何获得选择最短旋转方向的角度

    我的游戏中有一个角色必须平滑旋转才能达到所需的角度 考虑angle作为当前角度和touchAngle作为所需的角度 始终在 0 到 360 之间 我想在每次游戏更新中将 1 1 添加到当前角度以获得所需的角度touchAngle 问题是首先
  • 提交响应后是否可以从 servlet 过滤器转发或重定向?

    逻辑是过滤器被命中 条件不为真 所以它通过过滤器链 提交响应后 过滤器被命中 并且条件现在为真 请求属性已设置 它进去执行转发 但页面从未转发 我知道这与提交的响应有关 因为我测试了它在第一次到达链之前转发的不同逻辑 并且它确实转发成功 p
  • 如何开发具有混响功能的 iPhone 应用程序?

    我正在开发 iPhone 应用程序 如音频处理 我必须给音频添加一些效果 如果是桌面应用程序 有很多选择 我们可以获得很好的例子和完整的项目 比如大胆 但我想为 iPhone 开发 我有一个带有混响选项的应用程序 看看下面的链接 只是我看
  • 为什么 .NET 创建新的子字符串而不是指向现有字符串?

    从使用 Reflector 的简要观察来看 它看起来像String Substring 为每个子字符串分配内存 我的说法正确吗 我认为这没有必要 因为字符串是不可变的 我的根本目标是创建一个IEnumerable
  • 在 Windows 中更改模拟器电池电量

    如何更改 Windows 操作系统中模拟器的电池电量 从 50 更改为 70 且不充电 有一些指南 但它们都是针对 Ubuntu 的 Windows 支持telnet从命令提示符处 至少在 XP 和 Vista 上 如果您在其他 Windo
  • 从 FOP 的 JAR 加载字体

    我有一个 TTF 字体fonts我的应用程序位于 JAR 目录中 myapp jar fop config xml font ttf 我这样创建我的 FOP FopFactory fopFactory FopFactory newInsta
  • 使用 ACTION_VIEW 打开缓存目录中的文件

    我已经搜索这个有一段时间了 但我无法使其正常工作 让我解释 我有一个保存文件的 Android 应用程序 图像 文档 在缓存目录中 起初我曾经getExternalCacheDir 方法并将它们保存在那里 但因为它应该缓存在没有 SD 卡的
  • 如何解决 Visual Studio 编译器崩溃问题

    我们有一个大型的 Visual Studio 2005 C Mfc 解决方案 其中 1 个项目包含大约 1300 个源文件 大约有 650 个 h 和 650 个 cpp 文件 我们还使用 Boost 和一些其他库 COM MSXML Of
  • 如何在 Spring MVC 应用程序中测试 Aspect

    我有一个 Spring MVC 应用程序 我使用一个方面来捕获所有控制器方法中的异常 Component Aspect public class ControllerExceptionAspect private Logger logger
  • 嵌套函数是否存在等效的 override ?

    如果我有这个函数 我应该怎么做才能用我自己的自定义版本替换内部函数 def foo def bar I want to change this pass here starts a long list of functions I want