python - 如果包装器可以替代实例方法,为什么还要使用 types.MethodType?

标签 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):
        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 .该模块的主要目的主要是为您提供类的名称,否则这些类将很难引用,但需要注意的是,其中一些类也被称为 dictint.

您实际上很少需要使用这些名称来构造或子类化某些东西。那么你如何处理像 types.MethodType 这样的东西呢?用它来反省。

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

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

相关文章:

python - 扩展 numpy 数组维度并 reshape

python - 迭代Python列表的列表并删除每个子列表的最终索引,无需导入

python - 如何修复 "AttributeError: ' 设置的对象没有属性 'ROOT_URLCONF' “

Python: __init__() 正好需要 2 个参数(给定 3 个)

python - 如何过滤 pandas 数据框中特定列的第一和第三四分位数内的行?

c++ - 自动类型转换

java - 我可以将只有实例变量的类称为包装类吗?

cuda - 执行 openCL 的 cuda 包装器

python - 如何在 Heroku 上安装 ffmpeg

python - 如何防止通过 for 循环覆盖字典中的数据