我有一些愚蠢的代码与猴子匹配部分。以下示例仅供自学而非生产。
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解释器无法隐式传递obj
中的some_function
。但是当我进行内省并获得字节代码时,我有类似的方法表示(替换之前和之后)。
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)
请有人解释为什么会这样发生吗?
答案 0 :(得分:3)
大部分答案都在这里:https://wiki.python.org/moin/FromFunctionToMethod。长话短说:
def
始终会产生function
个对象method
只是函数,类和实例要使代码工作(基于每个实例进行monkeypatching),您必须手动调用将从函数,类和实例创建method
的机制。使用新式类时,最简单的解决方案是直接调用函数上的描述符协议,即:
obj.some_method = some_function.__get__(obj, type(obj))
当你在你的例子中使用旧式类时(这不是一个好主意),你可以使用types.MethodType
代替,但除非你遇到一些遗留代码,否则你会更好使您的课程成为新式课程(=>继承自object
)。