代码之家  ›  专栏  ›  技术社区  ›  Eric O. Lebigot

从第三方模块重写方法有多糟糕?

  •  9
  • Eric O. Lebigot  · 技术社区  · 15 年前

    用Python从另一个第三方模块重新定义类方法有多糟糕?

    实际上,用户可以创建包含 numbers with uncertainty ;理想情况下,我希望他们的代码运行时没有修改(与代码操作浮动矩阵时相比);特别是,如果矩阵的逆矩阵 m 仍然可以通过 m.I 尽管事实上 M.I 必须使用我自己的代码(原始 I 方法一般不起作用)。

    重新定义numpy.matrix.i有多糟糕?首先,它会篡改我不喜欢的第三方代码,因为它可能不可靠(如果其他模块也这样做呢?_)。另一个问题是,新的numpy.matrix.i是一个包装器,当原始的numpy.matrix.i时,它的开销很小。实际上,我可以应用它来获得逆矩阵。

    正在对numpy矩阵进行子类化,并且只更改它们的 方法更好?这将迫使用户更新他们的代码,并用 m = matrix_with_uncert(…) (而不是继续使用 numpy.matrix(…) ,对于一个浮点矩阵),但为了健壮性,这可能是一个应该接受的不便吗?矩阵反演仍然可以用 M.I 另一方面,如果用户可以用 numpy.matrix() 直接检查,无需检查数据类型。

    欢迎任何评论或其他方法!

    3 回复  |  直到 9 年前
        1
  •  11
  •   Alex Martelli    15 年前

    子类化(它确实涉及重写,正如通常使用的术语一样)通常比“monkey patching”(将修改过的方法填充到现有的类或模块中)要好得多,即使后者是可用的(内置类型,即在C中实现的类型,可以保护自己不受monkey patching的影响,而且大多数都是这样)。

    例如,如果您的功能依赖于monkey patching,那么在任何时候,如果您的monkey patching类升级为在C中实现(为了速度或者特别是为了防止monkey patching),它将中断并停止升级。第三方软件包的维护者讨厌猴子补丁,因为这意味着他们得到了倒霉的用户(他们不知道)的虚假错误报告,他们实际上使用了一个破坏第三方软件包的bug猴子补丁,后者(除非是坏猴子)是完美的。你已经提到了可能的性能冲击。

    从概念上讲,“不确定性数字矩阵”与“数字矩阵”是不同的概念。子类化清晰地表达了这一点,猴子修补试图隐藏它。这实际上是猴子修补的根本问题:一个通过全球隐藏手段进行操作的秘密渠道,没有清晰和透明。所有的许多实际问题在某种意义上都源于这个根本概念问题。

    强烈地 敦促您拒绝猴子修补,而支持干净的解决方案,如子类化。

        2
  •  1
  •   Alexander Poluektov    15 年前

    一般来说,重写那些…

    • 故意允许撤销
    • 以某种方式记录(满足 LSP 不会伤害

    如果满足这两个条件,则覆盖应该是安全的。

        3
  •  1
  •   Lennart Regebro    15 年前

    取决于你所说的“重新定义”。显然,你可以使用你自己的版本,完全没有问题。如果它是一个方法,也可以通过子类化来重新定义它。

    您还可以创建一个新方法,并将其修补到类中,该实践称为monkey_patching。像这样:

    from amodule import aclass
    
    def newfunction(self, param):
        do_something()
    
    aclass.oldfunction = newfunction
    

    这将使aclass的所有实例使用新函数而不是旧函数,包括任何“第四方”模块中的实例。这是可行的,非常有用,但它被认为是非常丑陋和最后的选择。这是因为aclass代码中没有任何内容可以建议您重写该方法,因此很难调试。更糟糕的是,当两个模块MonkeyPatch相同的东西时。那么你 真正地 弄糊涂了。