gpt4 book ai didi

python - Monkeypatching:将类上的方法替换为函数

转载 作者:行者123 更新时间:2023-11-28 16:36:56 24 4
gpt4 key购买 nike

我有一些愚蠢的代码,其中包含猴子匹配部分。以下示例仅供自学,不用于生产。

class MyClass:

def some_method(self):
print("some_method call")
self.yet_another_method()

def yet_another_method(self):
print('yet_another_method call')


def some_function(self):
print("some function call")
self.yet_another_method()

obj = MyClass()
obj.some_method()
obj.some_method = some_function
obj.some_method()

当我执行这段代码时,出现以下错误:

TypeError: non_class_some_method() missing 1 required positional argument: 'self'

很明显,Python 解释器不能在some_function 中隐式传递obj。但是当我进行自省(introspection)并获取字节码时,我有类似的方法表示(替换之前和之后)。

import dis
import inspect


class MyClass:

def some_method(self):
print("some_method call")
self.yet_another_method()

def yet_another_method(self):
print('yet_another_method call')


def some_function(self):
print("some function call")
self.yet_another_method()

obj = MyClass()
dis.dis(obj.some_method)
print(inspect.getargspec(obj.some_method))
obj.some_method = some_function
print("======================================================================")
dis.dis(obj.some_method)
print(inspect.getargspec(obj.some_method))

结果:

  8           0 LOAD_GLOBAL              0 (print) 
3 LOAD_CONST 1 ('some_method call')
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP

9 10 LOAD_FAST 0 (self)
13 LOAD_ATTR 1 (yet_another_method)
16 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
19 POP_TOP
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
======================================================================
16 0 LOAD_GLOBAL 0 (print)
3 LOAD_CONST 1 ('some function call')
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP

17 10 LOAD_FAST 0 (self)
13 LOAD_ATTR 1 (yet_another_method)
16 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
19 POP_TOP
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)

谁能解释一下为什么会这样?

最佳答案

大部分答案都在这里:https://wiki.python.org/moin/FromFunctionToMethod .长话短说:

  • def 总是产生一个函数对象
  • 一个方法只是函数、类和实例的一个薄的可调用包装器
  • 仅当函数是类的属性时才创建此包装器 - 而不是实例的属性时。

为了使您的代码正常工作(基于每个实例的 monkeypatching),您必须手动调用从函数、类和实例创建方法 的机制。当使用新式类时,最简单的解决方案是直接在函数上调用描述符协议(protocol),即:

obj.some_method = some_function.__get__(obj, type(obj))

当像您在示例中那样使用旧式类时(这不是一个好主意),您可以改用 types.MethodType,但实际上除非您坚持使用一些遗留代码你最好让你的类(class)成为新式类(class)(=> 从 object 继承)。

关于python - Monkeypatching:将类上的方法替换为函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24913165/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com