【问题标题】:Do something before and after method execution在方法执行之前和之后做一些事情
【发布时间】:2022-01-10 06:43:31
【问题描述】:

我试图在我的类中执行某些方法之前和之后执行一个操作。
首先我考虑使用装饰器来扩展功能,如下所示:

def decorator(f):
    def wrap(*args, **kwargs):
        print("before")
        f(*args, **kwargs)
        print("after")

    return wrap


class Foo(object):

    @decorator
    def do(self):
        print("This is do")


a = Foo()
a.do()

这会输出我想要的:

before
This is do
after

但后来我意识到,如果我想从 Foo 继承以扩展 do,那是行不通的,至少我这样做是行不通的:

class Bar(Foo):

    def do(self):
        super(Bar, self).do()
        print("This is the new implementation of do")


b = Bar()
b.do()

这将是输出,这是不正确的。 "after" 应该是最后要打印的内容:

before
This is do
after
This is the new implementation of do

也许还有另一种方法可以在Bar 中装饰do,所以它可以满足我的要求,但我不知道如何(如果有的话我想知道)并且每次都装饰do 不会这似乎不是一个好方法。

所以最后我想出了一个我认为不错的解决方案。定义__getattribute__so 它返回do 的包装器:

class Foo(object):
    def __getattribute__(self, name):
        attribute = super(Foo, self).__getattribute__(name)
        if name == "do":
            def wrap(*args, **kwargs):
                print("before")
                attribute(*args, **kwargs)
                print("after")
            return wrap

        else:
            return attribute

    def do(self):
        print("This is do")


class Bar(Foo):
    def __init__(self):
        super(Bar, self).__init__()

    def do(self):
        super(Bar, self).do()
        print("This is the new implementation of do")


a = Bar()
a.do()

这是一个好的解决方案吗?有什么缺点吗?我错过了可能在未来造成问题的东西?其他解决方法?

谢谢!!

【问题讨论】:

    标签: python inheritance methods


    【解决方案1】:

    您可以使用__wrapped__ 访问python3 中的包装函数,因为它是一个自定义装饰器,您需要使用functools.wraps 装饰器进行轻微修改。

    from functools import wraps
    
    def decorator(f):
        @wraps(f)
        def wrap(*args, **kwargs):
            print("before")
            f(*args, **kwargs)
            print("after")
    
        return wrap
    

    将装饰器重新应用到新的do() 并从旧的中剥离

    class Bar(Foo):
        @decorator
        def do(self):
            super(Bar, self).do.__wrapped__(super)
            print("This is the new implementation of do")
    

    你得到:

    before
    This is do
    This is the new implementation of do
    after
    

    【讨论】:

    • 谢谢!我知道@wraps(),但不知道__wrapped__ 的使用,这真的很好。我肯定会在未来使用它。有没有想过使用__getattribute__
    • 从概念上讲不是一个大粉丝,你正在处理一个 do() 特定问题并将其变成一个类范围的问题。
    【解决方案2】:

    您可以将 do() 的实现放在一个单独的方法中,该方法将在子类中覆盖,并且仅在基类中使用具有前/后处理的主要 do() 方法:

    class Foo:
        def _do(self): 
            # do your stuff
    
        def do(self):
            self.preProcessing()
            self._do()
            self.postProcessing()
    
    class Bar(Foo):
        def _do(self):
            super()._do()
            # do more stuff 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多