Python:如何向类的实例中注入新函数?
我尝试去修改 __mro__
,但是它是只读的。
我的使用场景是这样的:
从 pyodbc(一个数据库API)创建的连接对象,有一个叫做 'autocommit' 的属性。最近,我在 pyodbc 的基础上包了一层 SQLAlchemy 的数据库连接池,以更好地管理资源。这个新的数据库连接池会返回一个 _ConnectionFairy
,这是一个连接代理类,它不再提供 autocommit
这个属性。
我很想不去动第三方的代码。所以,继承 _ConnectionFairy
其实不是一个好选择(我可能需要重写连接池的类,以改变它创建连接代理的方式。想要查看源代码,可以点击 这里)。
一个不太优雅的解决方案是把所有出现的
conn.autocommit = True
都改成
# original connection object is accessible via .connection
conn.connection.autocommit = True
所以,我想知道是否有可能给 _ConnectionFairy
的实例注入一组 getter、setter 和属性。
1 个回答
13
你可以用下面的语法“扩展”几乎任何类:
def new_func(self, param):
print param
class a:
pass
a.my_func = new_func
b = a()
b.my_func(10)
更新
如果你想为某些方法创建一种包装,可以使用getattr和setattr来保存原始方法,并用你自己的实现替换它。我在我的项目中做过类似的事情,不过方式稍有不同:
这里有一个例子:
class A:
def __init__(self):
setattr(self, 'prepare_orig', getattr(self,'prepare'))
setattr(self, 'prepare', getattr(self,'prepare_wrapper'))
def prepare_wrapper(self,*args,**kwargs):
def prepare_thread(*args,**kwargs):
try:
self.prepare_orig(*args,**kwargs)
except:
print "Unexpected error:", sys.exc_info()[0]
t = threading.Thread(target=prepare_thread, args=args, kwargs=kwargs)
t.start()
def prepare(self):
pass
这段代码的意思是,其他开发者只需要在派生类中实现prepare方法,它就会在后台自动执行。这不是你问的内容,但我希望这能在某种程度上对你有所帮助。