所以如果我有一个方法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
方法更具吸引力,在这种情况下答案是显而易见的,这就是我所要求的:在哪种情况下,首选使用{ {1}}而不是像我演示的那样简单地写包装器?
答案 0 :(得分:1)
您需要或想要在types
模块中使用任何这种情况相当罕见,但我承认过去曾为types.ModuleType
提交了子类flexmock。这个模块的主要目的主要是为你提供那些本来很难引用的类的名称,但需要注意的是,其中一些类也被dict
或int
所知。
实际上很少需要使用这些名称来构造或子类化某些东西。那你用types.MethodType
之类的东西怎么办?用它来进行内省。
假设你想编写一个自动文档生成器。也许你把你的autodoc交给有问题的模块。使用types.FunctionType
,types.TypeType
和types.ClassType
(对于旧式类),您可以弄清楚模块中的功能和类是什么,并为每个类调用适当的文档格式化程序。对于每个类,您可以遍历其成员并使用types.MethodType
从其他属性中挑选出类的方法,并在适当时记录每个类。