在导入时装饰模块而不影响在其他功能方面实现的功能

时间:2014-03-17 19:27:44

标签: python wrapper decorator

我有一个与我合作的界面来声明几种验证方法。为简单起见,我们可以考虑三种方法。 verify_less_than()verify_equal()verify_less_than_equal()。 (参见下面的实施)。当我导入这些时,我想装饰它们,如果验证失败 - verify_less_than( 10, 5 ) - 将引发异常。

我已经让这个工作在前两个,但第三个功能给了我一个更难的时间。因为verify_less_than_equal是根据前两种方法定义的,如果第一次调用失败 - verify_less_than_equal( 5, 5 ) - 在调用第二次调用之前将抛出异常。

非常感谢对此的任何帮助

示例代码:

module.py

class needs_decoration():
    def verify_less_than( self, x, y ):
        return( x < y )

    def verify_equal( self, x, y ):
        return( x == y )

    def verify_less_than_equal( self, x, y ):
        return( self.verify_less_than( x, y ) or self.verify_equal( x, y ) )

implementation.py

import types
import module

def decorate( fn ):
    def wrapped( self, x, y ):
        res = fn( self, x, y )
        if res == False:
            raise Exception( 'Verification failed!' )
        return res
    return wrapped

for k, v in vars( module.needs_decoration ).items():
    if isinstance( v, types.FunctionType ):
        if not '__init__' in str( vars( module.needs_decoration )[ k ] ):
            vars( module.needs_decoration )[ k ] = decorate( v )

verifier = module.needs_decoration()
verifier.verify_less_than_equal( 5, 5 ) # This will raise an exception, and I would like it not to

1 个答案:

答案 0 :(得分:2)

您可以定义将保留未修饰的私有(下划线)方法,以便_verify_less_than_equal可以调用未修饰的函数。 for-loop然后可以添加公共API(没有下划线的方法),它们是私有方法的装饰版本:

import types

def add_decorators(cls):
    def decorate(fn):
        def wrapped(self, x, y):
            res = fn(self, x, y)
            if not res:
                raise ValueError('Verification failed! {}({}, {}) is False'
                                .format(fn.__name__, x, y))
            return res
        return wrapped

    for k, v in vars(cls).items():
        if isinstance(v, types.FunctionType):
            if k.startswith('__'): continue
            if k.startswith('_'):
                setattr(cls, k[1:], decorate(v))
    return cls

@add_decorators
class NeedsDecoration():
    def _verify_less_than(self, x, y):
        return x < y

    def _verify_equal(self, x, y):
        return x == y

    def _verify_less_than_equal(self, x, y):
        return self._verify_less_than(x, y) or self._verify_equal(x, y)

    def __init__(self): pass
verifier = NeedsDecoration()
assert verifier.verify_less_than_equal(5, 5)

根据需要,最后一行不会引发异常。