Python:将新函数注入到类的实例中?

时间:2011-01-17 23:36:21

标签: python

我试图操纵__mro__但它只读

用例如下:

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

我非常希望单独留下第三方代码。因此,_ConnectionFairy的继承实际上不是一个选项(我可能需要覆盖Pool类来更改它创建连接代理的方式。有关源代码,请参阅here

一个相当不太优雅的解决方案是改变

的所有出现
conn.autocommit = True

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

所以,我想知道是否有可能将一组getter,setter和property注入_ConnectionFairy的实例

1 个答案:

答案 0 :(得分:10)

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

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