代码之家  ›  专栏  ›  技术社区  ›  Nick

创建一个包装器类来围绕现有函数调用前置和后置函数?

  •  16
  • Nick  · 技术社区  · 17 年前

    例如,如果我有这门课。

    class Simple(object):
        def one(self):
            print "one"
    
        def two(self,two):
            print "two" + two
    
        def three(self):
            print "three"
    

    number = Simple()
    number.one()
    number.two("2")
    

    到目前为止,我已经编写了这个包装器类。..

    class Wrapper(object):
        def __init__(self,wrapped_class):
            self.wrapped_class = wrapped_class()
    
        def __getattr__(self,attr):
            return self.wrapped_class.__getattribute__(attr)
    
        def pre():
            print "pre"
    
        def post():
            print "post"
    

    我可以这样称呼它。..

    number = Wrapper(Simple)
    number.one()
    number.two("2")
    

    2 回复  |  直到 17 年前
        1
  •  25
  •   Matti Lyra    13 年前

    __getattr__ ,当原始属性可调用时,返回一个新的包装函数:

    class Wrapper(object):
        def __init__(self,wrapped_class):
            self.wrapped_class = wrapped_class()
    
        def __getattr__(self,attr):
            orig_attr = self.wrapped_class.__getattribute__(attr)
            if callable(orig_attr):
                def hooked(*args, **kwargs):
                    self.pre()
                    result = orig_attr(*args, **kwargs)
                    # prevent wrapped_class from becoming unwrapped
                    if result == self.wrapped_class:
                        return self
                    self.post()
                    return result
                return hooked
            else:
                return orig_attr
    
        def pre(self):
            print ">> pre"
    
        def post(self):
            print "<< post"
    

    number = Wrapper(Simple)
    
    print "\nCalling wrapped 'one':"
    number.one()
    
    print "\nCalling wrapped 'two':"
    number.two("2")
    

    Calling wrapped 'one':
    >> pre
    one
    << post
    
    Calling wrapped 'two':
    >> pre
    two2
    << post
    
        2
  •  2
  •   Nick    17 年前

    我刚刚注意到,在我的原始设计中,无法将args和kwargs传递给包装类,以下是更新的答案,将输入传递给包装函数。..

    class Wrapper(object):
    def __init__(self,wrapped_class,*args,**kargs):
        self.wrapped_class = wrapped_class(*args,**kargs)
    
    def __getattr__(self,attr):
        orig_attr = self.wrapped_class.__getattribute__(attr)
        if callable(orig_attr):
            def hooked(*args, **kwargs):
                self.pre()
                result = orig_attr(*args, **kwargs)
                self.post()
                return result
            return hooked
        else:
            return orig_attr
    
    def pre(self):
        print ">> pre"
    
    def post(self):
        print "<< post"