如何在Python中为实例动态设置方法?
如何在Python中为实例动态设置方法?
嘿,我看你尝试在运行时给实例动态设置方法,但遇到了实例属性方法调用报错的问题——类属性one能正常工作,但实例的two和three调用时都提示缺少self参数,对吧?这其实是Python的方法绑定机制在作怪,咱们一步步来解决它。
问题根源
当你把函数赋值给类属性时,Python会自动把它包装成一个绑定方法,调用实例的这个方法时,Python会自动把实例本身作为self参数传进去,所以a.one()能正常运行。
但如果你直接把函数赋值给实例属性,这个函数就只是个普通的函数对象,不会自动和实例绑定,调用时自然就不会自动传入self,所以才会报缺少参数的错误。
解决方案:手动绑定方法到实例
我们可以用types模块里的MethodType,把函数手动绑定到实例上,这样它就变成了实例的绑定方法,调用时会自动传入self。
先看修改后的代码:
import types def set_method(where_to_set: str): def the_method(self): print(where_to_set, '->', self) return the_method class A: one = set_method('as class attr `one`') two = None def __init__(self, necessary_variable): # 用MethodType把方法绑定到当前实例self上 self.two = types.MethodType(set_method(f'as instance overriden attr `two` with {necessary_variable}'), self) self.three = types.MethodType(set_method(f'as instance attr `three` with {necessary_variable}'), self) a = A('I`m important') try: a.one() except TypeError as e: print('one ->', e) try: a.two() except TypeError as e: print('two ->', e) try: a.three() except TypeError as e: print('three ->', e)
运行结果
修改后运行代码,输出就全部正常了:
as class attr `one` -> <__main__.A object at 0x7f0a1638e250> as instance overriden attr `two` with I`m important -> <__main__.A object at 0x7f0a1638e250> as instance attr `three` with I`m important -> <__main__.A object at 0x7f0a1638e250>
补充:其他实现方式
除了MethodType,你还可以用functools.partial来固定self参数,写法类似:
from functools import partial # 在__init__里这样赋值: self.two = partial(set_method(f'as instance overriden attr `two` with {necessary_variable}'), self)
不过MethodType是更标准的方式,因为它会真正创建一个绑定方法对象,行为和类里定义的方法更一致。
备注:内容来源于stack exchange,提问作者rzlvmp
相关产品推荐
相关产品推荐

