【问题标题】:Python Decorator override function argumentPython 装饰器覆盖函数参数
【发布时间】:2017-07-12 00:30:11
【问题描述】:

我正在尝试编写一个 python 装饰器来覆盖函数参数,但我真的不知道要在 inner() 函数中放置什么。在这里修改 args 的正确方法是什么?

  def override(*override_args, **override_kwargs): 
        def outer(f): 
            def inner(*args, **kwargs): 
                ...
                ...
            return inner
        return outer

    @override('Cat')
    def my_function(animal, **kwargs): 
        print animal
        print kwargs

    my_function('Mouse', k1='1', k2='10') 

【问题讨论】:

    标签: python decorator python-decorators


    【解决方案1】:
    def override(*override_args, **override_kwargs):
        def outer(f):
            def inner(*args, **kwargs):
                min_args_length = min(len(args), len(override_args))
                args = list(args)
                for i in xrange(min_args_length):
                    args[i] = override_args[i]
                kwargs.update(override_kwargs)
                return f(*args, **kwargs)
            return inner
        return outer
    
    @override('Cat', 'male', k1='0')
    def my_function(animal, **kwargs):
        print animal
        print kwargs
    
    my_function('Mouse', k1='1', k2='10')
    

    输出:

    Cat
    {'k2': '10', 'k1': '0'}
    

    解释:

    args 是一个元组,包含没有名称的 args,我们最多可以覆盖它们的 min(len(args), len(override_args))。

    kwargs 是一个包含命名 args 作为 key : value 对的字典。只需将 override_kwargs 更新为 kwargs

    我强烈建议您只覆盖命名参数“kwargs”以防止不匹配参数的顺序。

    【讨论】:

      【解决方案2】:
      class override_func_params(object):
          def __init__(self, *args, **kwargs):
              self.override_args = args
              self.override_kwargs = kwargs
      
          def __call__(self, func):
              def wrapper(*args, **kwargs):
                  if kwargs:
                      kwargs.update(self.override_kwargs)
                  if args:
                      args = list(args)
                      for index, value in enumerate(self.override_args):
                          try:
                              args[index] = value
                          except IndexError:
                              break
                      args = tuple(args)
                  return func(*args, **kwargs)
              return wrapper
      
      
      @override_func_params('a', k=1)
      def foo(*args, **kwargs):
          print args, kwargs
      

      不带参数调用。

      >>> foo()
      >>> (), {}
      

      带参数调用,参数被覆盖。

      >>> foo('b', k=2)
      >>> ('a',), {'k': 1}
      

      【讨论】:

        【解决方案3】:

        我已经简化了您的示例。请尝试了解装饰器中哪个位置的参数。

        def override(dec_animal):
            def outer(func):
                def inner(animal_to_be_ignored, **kwargs):
                    # print animal_to_be_ignored ==> This is mouse
                    return func(dec_animal, **kwargs)
                return inner
             return outer
        
        
        @override('Cat')
        def my_function(animal, **kwargs):
            print animal
            print kwargs
        
        
        my_function('Mouse', k1='1', k2='10')
        

        输出:

        Cat {'k2': '10', 'k1': '1'}

        【讨论】:

          猜你喜欢
          • 2017-04-09
          • 2014-07-21
          • 2015-10-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-27
          • 2020-01-07
          • 2013-01-19
          相关资源
          最近更新 更多