【问题标题】:How i can to inject code in class method in python?我如何在python的类方法中注入代码?
【发布时间】:2021-08-24 04:22:12
【问题描述】:

我如何在类方法中注入代码。我必须使用这么多方法(app_one app_two ...)。我认为代码不是美,并且看起来像是在多行中重复。我想知道如何重构这段代码?

class Main:
     def step_one(self):
         print("STEP 1")

     def step_tree(self):
         print("STEP 3")
     
     def app_one(self):
         self.step_one()
         /// do_something
         self.step_two()

     def app_two(self):
         self.step_one()
         /// do_something
         self.step_two()

     def app_three(self):
         self.step_one()
         /// do_something
         self.step_two()

感谢专家。

【问题讨论】:

  • ... 将/// do_something 放入一个方法中,然后在其他方法中调用该方法?

标签: python python-3.x class oop


【解决方案1】:

一种方法是使用装饰器:

from functools import wraps

def call_step_one_step_two(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        self.step_one()
        func(self, *args, **kwargs)
        self.step_two()
    return wrapper


class Main:
     def step_one(self):
        print("STEP 1")

     def step_two(self):
        print("STEP 3")

     @call_step_one_step_two
     def app_one(self):
        // do something

     @call_step_one_step_two
     def app_two(self):
        // do something

     @call_step_one_step_two
     def app_three(self):
        // do something

包装在这个装饰器中的所有方法总是在方法之前调用step_one,在方法之后调用step_two。但是,这不支持返回值。希望这就足够了。

【讨论】:

    【解决方案2】:

    我们可以定义一个decorator,它采用一个普通的实例方法,并将它变成一个你想要的序言和尾声。这是我们的装饰器的样子

    def wrapped_app(fn):
        def wrapped_fn(self, *args, **kwargs):
            self.step_one()
            fn(self, *args, **kwargs)
            self.step_three()
        return wrapped_fn
    

    所以给定一个函数fnwrapped_app 返回一个新函数(我们在本地调用wrapped_fn),它执行self.step_one(),然后是fn,然后是self.step_three()。我们现在可以在类中使用装饰器语法了

    class Main:
    
        def step_one(self):
            print("STEP 1")
    
        def step_three(self):
            print("STEP 3")
    
        @wrapped_app
        def app_one(self):
            print("App one")
    
        @wrapped_app
        def app_two(self):
            print("App two")
    
        @wrapped_app
        def app_three(self):
            print("App three")
    

    我们可以检查它是否工作如下

    >>> main = Main()
    >>> main.app_one()
    STEP 1
    App one
    STEP 3
    

    我们还可以更进一步。您当前的app_one 等人没有返回任何内容,但我们可能希望这些函数能够返回。对wrapped_fn 稍作修改将处理这种可能性。同样,我们可能还希望step_three 保证运行,即使在我们的应用程序功能失败或引发异常的情况下。我们可以使用try ... finally 这样做。

    def wrapped_app(fn):
        def wrapped_fn(self, *args, **kwargs):
            self.step_one()
            try:
                result = fn(self, *args, **kwargs)
            finally:
                self.step_three()
            return result
        return wrapped_fn
    

    【讨论】:

      【解决方案3】:

      这样的?

      class Main:
           def step_one(self):
               print("STEP 1")
      
           def step_tree(self):
               print("STEP 3")
           
           def app_one_function(self):
               # do_something_app_one_unique
      
           def app_two_function(self):
               # do_something_app_two_unique
      
           def app_three_function(self):
               # do_something_app_three_unique
      
           def run_app(self, function):
               self.step_one()
               function()
               self.step_two()
      

      或者你可以使用这样的装饰器

      def decorator(function):
          def decorated(cls):
              cls.step_one()
              function(cls)
              cls.step_two()
          return decorated
      
      class Main:
           def step_one(self):
               print("STEP 1")
      
           def step_tree(self):
               print("STEP 3")
           
           @decorator
           def app_one(self):
               # do_something_app_one_unique
      
           @decorator
           def app_two(self):
               # do_something_app_two_unique
      
           @decorator
           def app_three(self):
               # do_something_app_three_unique
      
      obj = Main()
      obj.app_one()
      obj.app_two()
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        • 2011-06-07
        • 2018-09-14
        • 2013-07-20
        • 2012-11-30
        相关资源
        最近更新 更多