使用类装饰器在每个方法的开头自动重新分配self .__ class__?

时间:2018-03-14 18:08:35

标签: python

我最近尝试过reload()。让我们考虑以下简单模块mother_and_child_in_same_file.py

class mother( object ):

    def foobar( self ):

        print "foobar mother"

class child( mother ):

    def foobar( self ):

        self.__class__ = child
        # None of the two following methods is correctly working after a reload,
        # except if we
        # add the previous line concerning __class__; then both methods work
        # correctly.
        mother.foobar( self )
        #super( child, self ).foobar()

        print "foobar child"

在剧本中使用:

import mother_and_child_in_same_file

a = mother_and_child_in_same_file.child()

a.foobar()

print "============ RELOAD"
reload( mother_and_child_in_same_file )

a.foobar()

导致预期输出

$ python mother_and_child_in_same_file_TEST.py 
foobar mother
foobar child
============ RELOAD
foobar mother
foobar child

但是只有在代码中解释的self.__class__被强制的情况下才会强制执行。 因此问题在于,现有物体可能会松散"使用reload()时他们的类,使得必须在这些对象的每个方法的开头重新分配self.__class__,这样在调用母亲时没有获得错误(如果我理解正确)。 这是相当沉重的,我试图使用类装饰器自动执行此操作。这是mother_and_child_in_same_file_decorator.py模块:

def my_decorator( cls ):

    def prepend_cls_instance_method_with_class_update( m ):

        def prepended_method( self, *args ):

            self.__class__ = cls
            print "After: self.__class__ = %s" % self.__class__
            m( self, *args )

        return prepended_method

    for method_name in dir( cls ):
        if method_name[:2] == "__":
            continue
        method = getattr( cls, method_name )
        if hasattr( method, '__call__' ):
            prepended_method = prepend_cls_instance_method_with_class_update( method )
            print "setattr( %s, '%s', %s )" % ( cls, method_name, prepended_method )
            setattr( cls
                    , method_name
                    , prepended_method )

    return cls

class mother( object ):

    def foobar( self ):

        print "foobar mother"

@my_decorator
class child( mother ):

    def foobar( self ):

        # None of the two following methods is correctly working.
        #super( child, self ).foobar()
        mother.foobar( self )

        print "foobar child"

使用它的脚本:

import mother_and_child_in_same_file_decorator as mother_and_child_in_same_file

a = mother_and_child_in_same_file.child()

a.foobar()

print "============ RELOAD"
reload( mother_and_child_in_same_file )

a.foobar()

这导致:

$ python mother_and_child_in_same_file_decorator_TEST.py 
setattr( <class 'mother_and_child_in_same_file_decorator.child'>, 'foobar', <function prepended_method at 0x7fd467568b18> )
Before: self.__class__ = <class 'mother_and_child_in_same_file_decorator.child'>
foobar mother
foobar child
============ RELOAD
setattr( <class 'mother_and_child_in_same_file_decorator.child'>, 'foobar', <function prepended_method at 0x7fd467568c80> )
Before: self.__class__ = <class 'mother_and_child_in_same_file_decorator.child'>
Traceback (most recent call last):
  File "mother_and_child_in_same_file_decorator_TEST.py", line 10, in <module>
    a.foobar()
  File "/home/local/mse6s3/src/python/test/reload_and_super/mother_and_child_in_same_file/mother_and_child_in_same_file_decorator.py", line 9, in prepended_method
    m( self, *args )
  File "/home/local/mse6s3/src/python/test/reload_and_super/mother_and_child_in_same_file/mother_and_child_in_same_file_decorator.py", line 43, in foobar
    mother.foobar( self )
TypeError: unbound method foobar() must be called with mother instance as first argument (got child instance instead)

我尝试过此代码的不同变体,但没有成功。我的代码出了什么问题?提前谢谢。

2 个答案:

答案 0 :(得分:0)

重新加载后重新创建对象。它对我来说看起来更简单,它会起作用:

import mother_child

a = mother_child.child()
a.foobar()
print "============ RELOAD"
reload(mother_child)
a = mother_child.child()
a.foobar()

答案 1 :(得分:0)

@ShadowRanger(我忘了谢谢你的回答)。实际上在我的情况下,由于以下原因,在开发期间需要reloads()。 Python解释器嵌入在用C ++编写的软件中。 &#34;嵌入式翻译&#34;允许访问一些C ++数据;除此之外,它允许运行一些Python&#34; apps&#34; (在带有GUI的小型应用程序中)在C ++软件的上下文中(即能够访问和修改某些C ++数据)。

在开发这样的应用程序时,当然需要在每次修改后一次又一次地运行它。这使得reloads()成为必需,因为嵌入式解释器在每次运行之间保持活动状态。另一种可能性是在重新启动App之前重新启动嵌入式Python解释器,但目前这是不可能的。

reloads()会出现问题,因为可以执行两个或多个相同的&#34; apps&#34;上面提到的嵌入式解释器。如果导入的模块中存在重新加载,则在第一个创建的对象中启动&#34; apps&#34;不承认他们的母亲/孩子(错误类似于我原来的帖子出现)。这就是为什么在这个框架中现在很明显我应该(i)仅在开发期间使用reload()(调试标志),(ii)只运行一个&#34; app&#34;在开发期间 - 多个应用程序&#34;同时运行应该只在发布代码中测试(没有调试标志---所以没有reload())。