Python 如果包装器可以替换实例方法,那么为什么要使用types.MethodType呢?

Python 如果包装器可以替换实例方法,那么为什么要使用types.MethodType呢?,python,python-2.7,wrapper,Python,Python 2.7,Wrapper,因此,如果我有一个方法为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):

因此,如果我有一个方法为
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
稍后,我继续在
A
类的一个实例上替换
obj.foo
,一切正常

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方式

我觉得我经常看到使用
类型
库的建议,有些人似乎想要策略模式之类的东西——不总是这样,但往往足以让许多用户忽视Python似乎已经具备处理能力的东西。正如在这里给出的明确例子,促使编码人员在要求更改之前“先看语言”寻找可能已经存在的功能一样——我认为他的演讲更倾向于过度编码或出去写政治公众人物,但我认为它也适用于这里——当包装器是他们所需要的全部时,是否应该转向库


因此,除非有什么东西使得
类型
方法更具吸引力,在这种情况下答案是显而易见的,否则我要问的是:在什么情况下使用
类型.MethodType
而不是像我刚才演示的那样简单地编写包装器,这是一种比较少见的情况,您需要或想要使用
类型
模块中的任何内容,尽管我承认过去有子类
类型.ModuleType
。本模块的主要目的是为您提供否则很难引用的类的名称,但需要注意的是,其中一些类也可以通过
dict
int
等方式来识别

实际上,您很少需要使用这些名称来构造或子类化某些内容。那么您如何处理
types.MethodType
?用它来反省


假设您想编写一个自动文档生成器。也许你可以把有问题的模块交给autodoc。使用
types.FunctionType
types.TypeType
,以及可能的
types.ClassType
(对于旧式类),您可以确定模块中哪些是函数和类,并为每个函数和类调用适当的文档格式化程序。对于每个类,您可以遍历其成员,并使用
types.MethodType
将类的方法与其其他属性进行排序,并根据需要记录每个类。

首选
类型的源代码。MethodType
?没有真实的例子,很难回答你的问题。根据我的经验,普通的高阶函数(你似乎称之为decorators)在大多数情况下都是可以的。听起来你是在建议一个人可以编写一堆高阶函数(甚至是普通函数)并将它们分配给对象实例,而不是在类级别定义它们以避免某些事情?另一条评论:这感觉像是javascripty。@erewok-也许没那么疯狂,但我知道你在那里做了什么。我不知道我在“避免”什么;例如,如果我只是在谈论战略模式,这看起来非常棒。@agf-Hmm,我认为我的语言是误导性的-看起来这就是我要问的,不是吗?我要改写我的问题——我想我更好奇的是,为什么一个库有一个简单模仿语言特性的方面。@Stick更有意义。没错,所有方法都是自动传入它们绑定到的对象,而不是手动传入。在Python3中,未绑定方法和函数之间没有任何区别;在Python2中,它们的类型略有不同。有趣的是,有多少用于在运行时实现新方法的解决方案引用了这个库。这就是我提出问题的原因;我通常认为,如果我找到了一种用更少的代码或更少的努力来做某事的方法,那么我一定是做错了。然而,在这种罕见的情况下,我似乎真的发现了什么!