Hub*_*rio 8 python monkeypatching
我似乎无法修补__call__类实例的方法(是的,我想修补单个实例,而不是所有实例).
以下代码:
class A(object):
def test(self):
return "TEST"
def __call__(self):
return "EXAMPLE"
a = A()
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))
a.__call__ = lambda : "example"
a.test = lambda : "test"
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))
print(a())
print("Explicit call: {0}".format(a.__call__()))
print(a.test())
Run Code Online (Sandbox Code Playgroud)
输出:
call method: <bound method A.__call__ of <__main__.A object at 0x7f3f2d60b6a0>>
test method: <bound method A.test of <__main__.A object at 0x7f3f2d60b6a0>>
call method: <function <lambda> at 0x7f3f2ef4ef28>
test method: <function <lambda> at 0x7f3f2d5f8f28>
EXAMPLE
Explicit call: example
test
Run Code Online (Sandbox Code Playgroud)
虽然我想输出:
...
example
Explicit call: example
test
Run Code Online (Sandbox Code Playgroud)
我如何monkeypatch __call__()?为什么我不能像修补其他方法那样修补它?
所以,正如JJ Hakala所评论的那样,Python真正做的是调用:
type(a).__call__(a)
Run Code Online (Sandbox Code Playgroud)
因此,如果我想覆盖该__call__方法,我必须覆盖__call__一个类,但如果我不想影响同一个类的其他实例的行为,我需要使用overriden __call__方法创建一个新类.
所以如何覆盖的示例__call__将如下所示:
class A(object):
def test(self):
return "TEST"
def __call__(self):
return "EXAMPLE"
def patch_call(instance, func):
class _(type(instance)):
def __call__(self, *arg, **kwarg):
return func(*arg, **kwarg)
instance.__class__ = _
a = A()
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))
patch_call(a, lambda : "example")
a.test = lambda : "test"
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))
print("{0}".format(a()))
print("Explicit a.__call__: {0}".format(a.__call__()))
print("{0}".format(a.test()))
print("Check instance of a: {0}".format(isinstance(a, A)))
Run Code Online (Sandbox Code Playgroud)
运行它会产生以下输出:
call method: <bound method A.__call__ of <__main__.A object at 0x7f404217a5f8>>
test method: <bound method A.test of <__main__.A object at 0x7f404217a5f8>>
call method: <bound method patch_call.<locals>._.__call__ of <__main__.patch_call.<locals>._ object at 0x7f404217a5f8>>
test method: <function <lambda> at 0x7f404216d048>
example
Explicit a.__call__: example
test
Check instance of a: True
Run Code Online (Sandbox Code Playgroud)
对于自定义类,只有在对对象的类型(而不是在对象的实例字典中)定义的情况下,才能保证对特殊方法的隐式调用可以正常工作。该行为是以下代码引发异常的原因:
Run Code Online (Sandbox Code Playgroud)>>> class C: ... pass ... >>> c = C() >>> c.__len__ = lambda: 5 >>> len(c) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'C' has no len()
来源:https : //docs.python.org/3/reference/datamodel.html#special-lookup
| 归档时间: |
|
| 查看次数: |
1228 次 |
| 最近记录: |