关于python:如何通过猴子修补来替换类?

How can I replace the class by monkey patching?

我如何替换ORM类-所以它不应该导致递归!!!!

问题:原始类具有超级调用,当它被替换时,它会导致自继承,并导致最大递归深度超过异常。也就是说,类ORM正在调用super(ORM,self)….ORM已被另一个继承原始ORM的类所取代…

包裹!

1
2
3
4
5
6
7
addons  __init__.py  osv  run_app.py

./addons:
__init__.py  test_app1.py  test.py

./osv:
__init__.py  orm.py

ORM.py的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class orm_template(object):
    def __init__(self, *args, **kw):
        super(orm_template, self).__init__()    
    def fields_get(self, fields):
        return fields    
    def browse(self, id):
        return id

class orm(orm_template):
    def __init__(self, *args, **kw):
        super(orm, self).__init__(*args, **kw)    
    def fields_get(self, fields, context = None):
        return super(orm, self).fields_get(fields)    
    def read(self, fields):
        return fields

加载项/init.py的内容

1
2
3
4
import test    
def main(app):
    print"Running..."
    __import__(app, globals(), locals())

加载项/test.py的内容

1
2
3
4
5
6
7
8
9
10
from osv import orm
import osv
class orm(orm.orm):
    def __init__(self, *args, **kw):
        super(orm, self).__init__(*args, **kw)    
    def fields_get(self, *args, **kw):
        print"my fields get................."
        return super(orm, self).fields_get(*args, **kw)    
osv.orm.orm = orm
print"replaced.........................."

试验内容附录1.py

1
2
3
4
5
6
from osv.orm import orm    
class hello(orm):
    _name = 'hellos'    
    def __init__(self, *args, **kw):
        super(hello, self).__init__(*args, **kw)    
print hello('test').fields_get(['name'])

run-app.py的内容

1
2
import addons
addons.main('test_app1')

产量

1
2
3
4
5
6
7
8
>>>python run_app.py

replaced..........................
Running...
...
...
super(orm, self).__init__(*args, **kw)
RuntimeError: maximum recursion depth exceeded

我也看到过类似的问题


您的addons/test.py需要获取并保留对原始orm.orm的引用,并使用它而不是替换版本。即。:

1
2
3
4
5
6
7
8
9
10
11
from osv import orm
import osv
original_orm = osv.orm
class orm(original_orm):
    def __init__(self, *args, **kw):
        super(orm, self).__init__(*args, **kw)    
    def fields_get(self, *args, **kw):
        print"my fields get................."
        return super(orm, self).fields_get(*args, **kw)    
osv.orm.orm = orm
print"replaced.........................."

所以MonkeyPatched在类中继承的是原始的而不是它本身,就像您在设置中所拥有的那样。顺便说一句,如果你能通过更好地设计osv模块(例如,设置ORM的setter函数)来避免猴子修补,你会更高兴;-。