Skip to main content
 首页 » 编程设计

Python:将新函数注入(inject)类的实例

2025年05月04日10bjzhanghao

我试图操纵 __mro__ 但它是只读的

用例如下:

从 pyodbc(一个 DBAPI)创建的连接对象用于提供一个名为“autocommit”的属性。最近我在 pyodbc 周围包装了一个 SQLAlchemy 数据库连接池,以便更好地管理资源。新的数据库池将返回一个 _ConnectionFairy,一个连接代理类,它不再公开 autocommit 属性。

我非常想单独留下第三方代码。所以继承 _ConnectionFairy 并不是一个真正的选择(我可能需要重写 Pool 类来改变它创建连接代理的方式。有关源代码,请参阅 here )

一个不太优雅的解决方案是改变所有出现的

conn.autocommit = True 

到

# original connection object is accessible via .connection 
conn.connection.autocommit = True  

所以,我想知道是否有可能向 _ConnectionFairy 的实例注入(inject)一组 getter、setter 和属性

请您参考如下方法:

您可以使用以下语法“扩展”几乎任何类:

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 方法,它将在后台执行。这不是你问的,但我希望它能以某种方式帮助你。