猴子补丁 Python 类

发布于 2024-09-24 06:16:57 字数 322 浏览 1 评论 0原文

我有一个类,位于一个单独的模块中,我无法更改它。

from module import MyClass

class ReplaceClass(object)
  ...

MyClass = ReplaceClass

除了这个文件之外,这不会改变 MyClass 的其他任何地方。但是,如果我像这样向类添加一个方法,

def bar():
   print 123

MyClass.foo = bar

它将起作用,但 foo 方法也将在其他地方可用。

如何完全替换类而不是替换方法呢?

I've got a class, located in a separate module, which I can't change.

from module import MyClass

class ReplaceClass(object)
  ...

MyClass = ReplaceClass

This doesn't change MyClass anywhere else but this file. However if I add a method to the class like this

def bar():
   print 123

MyClass.foo = bar

it will work, but the foo method will be available everywhere else as well.

How can I replace the class completely instead of replacing the method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

素罗衫 2024-10-01 06:16:57
import module
class ReplaceClass(object):
    ....
module.MyClass = ReplaceClass
import module
class ReplaceClass(object):
    ....
module.MyClass = ReplaceClass
奶茶白久 2024-10-01 06:16:57

当您最需要的是限定名称时,请避免使用from ... import(可怕的;-)方式来获取裸名。一旦你以正确的 Python 方式做事:

import module

class ReplaceClass(object): ...

module.MyClass = ReplaceClass

这样,你就可以对 module 对象进行猴子修补,这就是你所需要的,并且当该模块用于其他模块时它将起作用。使用 from ... 形式,您只是没有拥有模块对象(这是查看大多数人使用 from 的明显缺陷的一种方法。 ..),所以你的情况显然更糟;-);

我建议使用 from 语句的一种方法是从包中导入模块:

from some.package.here import amodule

这样您仍然可以获得模块对象,并且对该模块中的所有名称使用限定名称。

Avoid the from ... import (horrid;-) way to get barenames when what you need most often are qualified names. Once you do things the right Pythonic way:

import module

class ReplaceClass(object): ...

module.MyClass = ReplaceClass

This way, you're monkeypatching the module object, which is what you need and will work when that module is used for others. With the from ... form, you just don't have the module object (one way to look at the glaring defect of most people's use of from ...) and so you're obviously worse off;-);

The one way in which I recommend using the from statement is to import a module from within a package:

from some.package.here import amodule

so you're still getting the module object and will use qualified names for all the names in that module.

凡尘雨 2024-10-01 06:16:57

我不过是一颗鸡蛋。 。 。 。也许这对于非新手来说是显而易见的,但我需要 from some.package.module import module 习惯用法。

我必须修改 GeneralHelpfulClass 的一种方法。这失败了:

import some.package.module

class SpeciallyHelpfulClass(some.package.module.GenerallyHelpfulClass): 
    def general_method(self):...

some.package.module.GenerallyHelpfulClass = SpeciallyHelpfulClass

代码运行了,但没有使用重载到 SpeciallyHelpfulClass 上的行为。

这有效:

from some.package import module

class SpeciallyHelpfulClass(module.GenerallyHelpfulClass): 
    def general_method(self):...

module.GenerallyHelpfulClass = SpeciallyHelpfulClass

我推测 from ... import 习惯用法“获取模块”,正如 Alex 所写,因为它将被包中的其他模块拾取。进一步推测,较长的点引用似乎通过长点引用导入将模块带入命名空间,但不会更改其他命名空间使用的模块。因此,对导入模块的更改只会出现在进行更改的名称空间中。就好像同一模块有两个副本,每个副本都可以在略有不同的参考下使用。

I am but an egg . . . . Perhaps it is obvious to not-newbies, but I needed the from some.package.module import module idiom.

I had to modify one method of GenerallyHelpfulClass. This failed:

import some.package.module

class SpeciallyHelpfulClass(some.package.module.GenerallyHelpfulClass): 
    def general_method(self):...

some.package.module.GenerallyHelpfulClass = SpeciallyHelpfulClass

The code ran, but didn't use the behaviors overloaded onto SpeciallyHelpfulClass.

This worked:

from some.package import module

class SpeciallyHelpfulClass(module.GenerallyHelpfulClass): 
    def general_method(self):...

module.GenerallyHelpfulClass = SpeciallyHelpfulClass

I speculate that the from ... import idiom 'gets the module', as Alex wrote, as it will be picked up by other modules in the package. Speculating further, the longer dotted reference seems to bring the module into the namespace with the import by long dotted reference, but doesn't change the module used by other namespaces. Thus changes to the import module would only appear in the name space where they were made. It's as if there were two copies of the same module, each available under slightly different references.

抱着落日 2024-10-01 06:16:57
import some_module_name

class MyClass(object): 
     ... #copy/paste source class and update/add your logic

some_module_name.MyClass = MyClass

最好不要在替换时更改类的名称,因为不知何故有人可能使用 getattr 引用了它们 - 这将导致失败,如下所示

getattr(some_module_name, 'MyClass') -->如果你用 ReplaceClass 替换了 MyClass ,这将会失败!

import some_module_name

class MyClass(object): 
     ... #copy/paste source class and update/add your logic

some_module_name.MyClass = MyClass

Its preferable not to change the name of class while replacing, because somehow someone may have referenced them using getattr - which will result in fail like below

getattr(some_module_name, 'MyClass') --> which will fail if you have replaced MyClass by ReplaceClass !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文