4

一日一技:Python如何动态替换对象的方法?

 1 year ago
source link: https://www.kingname.info/2023/01/01/python-replace-method/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一日一技:Python如何动态替换对象的方法?

2023-01-01

2

522

2 分钟

今天有同学在公众号粉丝群问了这样一个问题:

20220719112119.png

他的问题,简单来说,就是想动态替换一个对象的实例方法,简化代码如下:

class Test:
def __init__(self, name):
self.name = name

def work(self, job):
print(f'{self.name}正在{job}')

def work(self, job1, job2):
print(f'{self.name}正在同时做两个工作,分别是{job1}和{job2}')

t = Test('kingname')
t.work = work

当我们在替换之前,直接运行t.work('job'),效果如下:

20220719112403.png

这个同学期望在替换以后,运行t.work('job1', 'job2'),能够输出:kingname正在同时做两个工作,分别是job1和job2。但上面的代码,直接运行以后会报错,如下图所示:

20220719112613.png

这说明,替换以后,在调用t.work的时候,Python 不会自动把self传入到第一个参数。

在以前的文章里面,我们已经讲过,实例方法的第一个参数self,就是这个实例对象自身。我们可以写一段代码来验证这一点:

class Test:
def __init__(self, name):
self.name = name

def work(self, job):
print(f'{self.name}正在{job}')

def check(self, instance):
print(f'self的内存地址是:{id(self)}')
print(f'instance 的内存地址是:{id(instance)}')
print('self与 instance 就是同一个对象:', self is instance)


t = Test('kingname')
t.check(t)

运行效果如下图所示:

20220719112903.png

知道这一点以后,要解决动态替换以后报错的问题,最简单的方法就是手动把实例对象作为第一个参数传入进去,如下图所示:

20220719113047.png

但这样做显然很麻烦,每次都要手动传入第一个实例对象。有没有什么办法能省略它呢?这个时候,如果你记得我公众号里面的这篇文章偏函数:在Python中设定默认参数的另一种办法,那么你就有办法了。使用偏函数,提前把第一个参数固定下来,就能解决问题:

from functools import partial
def work(self, job1, job2):
print(f'{self.name}正在同时做两个工作,分别是{job1}和{job2}')

simple_work = partial(work, t)
t.work = simple_work

运行效果如下图所示:

20220719113543.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK