因此,如果我有一个使用方法foo的类:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def foo(self):
        return "Hey I am called %s." % self.name


我决定做一个包装:

def bar(obj, func):
    def inner(*args, **kwargs):
        print "I am %d years old." % obj.age
        return func(*args, **Kwargs)
    return inner


然后,我继续在obj.foo类的实例上替换A,一切都很好。

Stick = A('Stick', 32)
Stick.foo = bar(Stick, Stick.foo)
Stick.foo()
>>> I am 32 years old.
>>> Hey I am called Stick.


这样就可以了,但是如果我省略了return func(*args, **kwargs)位,它的作用就好像它只是以与使用types.MethodType快速替换实例方法时所期望的方式替换方法一样。

def bar(obj):
    def inner(*args, **kwargs):
        return "I am %d years old." % obj.age
    return inner
Stick.foo = bar(Stick)
Stick.foo()
>>> I am 32 years old.


因此,也许这种方式会产生某种开销,或者这种实施策略模式的方式也会带来其他缺陷,但是……这似乎效果很好。与出于编写其中包含单词types.MethodType的功能而引入self相比,我不清楚为什么为什么导入types.MethodType而不是仅使用不返回原始方法的包装程序更受欢迎? ,或使用分配语法而不是@decorator的处理方式。

我觉得我经常看到使用types库的建议,该库似乎在某人似乎想要某种策略模式的情况下-并非总是如此,但经常出现在很多用户可能忽略了Python似乎已经具备的功能的地方处理。就像在this speech from PyCon 2009中,给出了清晰的示例,敦促编码人员“先寻找语言”以寻求在进行更改之前可能已经存在的功能-我相信他的演讲的重点更多是针对过度编码或出并编写PEP,但我认为它也适用于此-当只需要包装器时,是否应该转向图书馆?

因此,除非有某种使types方法更具吸引力的方法,在这种情况下答案很明显,这就是我要问的问题:在哪种情况下,首选使用types.MethodType而不是简单地编写包装器像我展示的那样?

最佳答案

尽管我会承认过去曾经为flexmock子类化types,但您很少需要或想要在types.ModuleType模块中使用任何东西的情况很少发生。该模块的主要目的主要是为您提供类的名称,否则这些类将很难引用,但需要注意的是,某些类也被诸如dictint之类的东西所熟知。

实际上,很少真正需要使用这些名称来构造或子类化某些东西。那么,您如何处理types.MethodType之类的东西?使用它进行内省。

假设您想编写一个自动文档生成器。也许您将问题自动交给模块。使用types.FunctionTypetypes.TypeType以及可能的types.ClassType(对于旧式类),您可以找出模块中的什么是函数和类,并为每个函数和类调用适当的文档格式化程序。对于每个类,您可以遍历其成员,并使用types.MethodType从其其他属性中整理出该类的方法,并适当地记录每个方法。

关于python - 如果包装程序可以替换实例方法,为什么还要使用types.MethodType?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22433249/

10-12 21:38