不修改源码条件下修改类方法,咋听起来是一件扯淡的事情,但对python来说,并非难事。
场景如下,先定义一个类
class Demo():
def readfile(self, filename):
"""
读取文件内容,这里简化为输出文件名称
:param filename:
:return:
"""
print(filename)
demo = Demo()
demo.readfile('/data/1.txt')
demo.readfile('/data/2.txt')
demo.readfile('/data/3.txt')
这份程序一直运行在linux系统下,可突然间有了变化,要求也可以在windows下运行,这三份文件都存储在d:/data/目录下,文件名称不变。注意,是一份程序即可在linux下运行也可以在windows下运行。
此时你首先想到的是修改Demo类的radfile方法,根据程序运行所在系统来决定文件路径,这是一个非常正确的做法,但这样就得修改Demo类。修改Demo类有问题吗,如果Demo类是你自己写的,那当然没有问题,但假设Demo类不是你写的,而是第三方包提供的,或者是python内置的呢,这种情况下你就不能修改其源码。
面对此种困境,还存在一个常规的解决方案,自定义一个继承Demo的类,MyDemo, 重写readfile方法。这样,只需要修改demo实例就可以了
demo = MyDemo()
这个方案可行,但我要做的,是更加硬核的方法,在运行状态下修改Demo类的readfile方法。我的思路如下
代码实现如下
class Demo():
def readfile(self, filename):
"""
读取文件内容,这里简化为输出文件名称
:param filename:
:return:
"""
print(filename)
def readfile(self, filename):
# 这里先判断所在系统,修改filename, 本文未实现这部分
self.readfileOrigin("修改后的:" + filename)
if getattr(Demo, 'readfileOrigin', None) is None:
setattr(Demo, 'readfileOrigin', Demo.readfile)
setattr(Demo, 'readfile', readfile)
demo = Demo()
demo.readfile('/data/1.txt')
demo.readfile('/data/2.txt')
demo.readfile('/data/3.txt')
我所描述的场景你或许觉得很极端,但最近在工作中却真实的遇到了。手里负责的工作是将部分pyspark任务迁移至阿里云的maxcompute,涉及到读写hdfs的地方要提供不同的路径,在公司内集群运行是hdfs路径,在maxcompute上运行需要提供oss路径。为了尽可能少的修改源码,我使用上面的方法修改了SparkContext.textFile 和 SparkContext.addFile方法。
QQ交流群: 211426309