可以对Python核心类型的方法进行猴子补丁吗?
Ruby可以给数字类和其他核心类型添加方法,这样就能实现一些特定的效果:
1.should_equal(1)
但是,似乎Python做不到这一点。这个说法是真的吗?如果是真的,为什么会这样?是不是因为类型不能被修改?
我不想讨论猴子补丁的不同定义,我只想专注于上面的例子。我已经得出结论,确实无法做到,正如你们中的一些人所回答的那样。但我希望能更详细地解释一下为什么不能做到,也许还可以说说如果Python有哪个功能的话,可以实现这个。
回答你们中的一些人:我可能想这样做的原因只是为了美观和可读性。
item.price.should_equal(19.99)
这样写更像英语,清楚地表明了哪个是测试值,哪个是期望值,而不是:
should_equal(item.price, 19.99)
这个概念是基于Rspec和其他一些Ruby框架的。
15 个回答
你可以做到这一点,不过需要一点小技巧。幸运的是,现在有一个叫“Forbidden Fruit”的模块,它可以让你很简单地修改内置类型的方法。你可以在这里找到它:
http://clarete.github.io/forbiddenfruit/?goback=.gde_50788_member_228887816
或者在这里:
https://pypi.python.org/pypi/forbiddenfruit/0.1.0
根据你最初的问题示例,写完“should_equal”这个函数后,你只需要这样做:
from forbiddenfruit import curse
curse(int, "should_equal", should_equal)
然后就可以开始使用了!另外,还有一个“reverse”函数可以用来移除已经修改的方法。
你这里说的“猴子补丁”到底是什么意思?其实有几种稍微不同的定义,你可以看看这个链接。
如果你是问“能不能在程序运行时改变一个类的方法?”那么答案是肯定的,当然可以:
class Foo:
pass # dummy class
Foo.bar = lambda self: 42
x = Foo()
print x.bar()
如果你是问“能不能在程序运行时改变一个类的方法,并且让这个类的所有实例都跟着改变?”那么答案也是可以的。只需要稍微调整一下顺序:
class Foo:
pass # dummy class
x = Foo()
Foo.bar = lambda self: 42
print x.bar()
不过,对于某些内置类,比如 int
或 float
,你是不能这样做的。这些类的方法是用C语言实现的,为了让实现更简单和高效,牺牲了一些抽象。
我其实不太明白为什么你想要改变内置数字类的行为。如果你需要改变它们的行为,直接去创建一个子类吧!!