所以如果我有一个方法为 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.
所以也许以这种方式产生了某种开销,或者这种实现策略模式的方式存在一些其他缺陷,但是......这似乎很有效。与为了编写其中包含单词 self
的函数而引入 types.MethodType
相比,我不清楚为什么要导入 types.MethodType
比简单地使用不返回原始方法的包装器,或者使用赋值语法而不是 @decorator 做事的方式更受欢迎。
我觉得我经常看到使用 types
库的建议,其中有人似乎想要策略模式之类的东西 - 并非总是如此,但经常足以让许多用户似乎忽略了一些东西Python 似乎已经具备处理的能力。如 this speech from PyCon 2009其中给出了明确的例子,敦促编码人员在要求更改之前“首先查看语言”以获得可能已经存在的功能——我相信他演讲的弧线更多的是针对过度编码或出去写一个 PEP ,但我认为它也适用于此——当他们只需要一个包装器时,是否应该转向图书馆?
所以除非有什么东西可以使 types
方法更有说服力,在这种情况下答案很明显,这就是我要问的:在哪种情况下它更受欢迎使用 types.MethodType
而不是像我演示的那样简单地编写包装器?
最佳答案
您需要或想要在 types
模块中使用任何东西的情况相当罕见,尽管我承认有 types.ModuleType 的子类
过去为 flexmock .该模块的主要目的主要是为您提供类的名称,否则这些类将很难引用,但需要注意的是,其中一些类也被称为 dict
或 int
.
您实际上很少需要使用这些名称来构造或子类化某些东西。那么你如何处理像 types.MethodType
这样的东西呢?用它来反省。
假设您想编写一个自动文档生成器。也许你把你的 autodoc 交给了有问题的模块。使用 types.FunctionType
、types.TypeType
,也许还有 types.ClassType
(对于旧式类),您可以找出该模块是函数和类,并为每个函数和类调用适当的文档格式化程序。对于每个类,您可以遍历其成员并使用 types.MethodType
从类的其他属性中挑选出该类的方法,并根据需要对每个方法进行记录。
关于python - 如果包装器可以替代实例方法,为什么还要使用 types.MethodType?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22433249/