Python装饰器:如何通过装饰器列出包装函数

时间:2016-08-26 13:11:44

标签: python python-decorators

如果我不知道包装函数的名称,是否可以使用python装饰器来标记方法,并将其用于以后的使用?

以下是示例,我不知道method_with_custom_name的名称:

@run_this_method
def method_with_custom_name(my_arg):
    return "The args is: " + my_arg

def _init_and_run():
    # Here, I want to get and call method_with_custom_name
    # but I don't know it's name, 
    # so the next line isn't valid.
    return run_this_method()(my_arg_value)

def run_this_method(m):
    def w(my_arg):
        _do_some_magic(my_arg, m)
    return w

def _do_some_magic(callback_arg, callback):
     if some_checks():
          callback(callback_arg)

那么如何获得包含@run_this_method

的方法列表

2 个答案:

答案 0 :(得分:2)

如果需要跟踪装饰器修饰的所有函数和方法,则需要创建全局变量来注册所有这些函数和方法。我修改了您的代码:

functions_registry

您可以创建用作装饰器的类,并在实体字段中注册函数,而不是使用全局变量class FunDecorator: def __init__(self): self.registry = [] def __call__(self, m): "This method is called when some method is decorated" self.registry.append(m) #Add function/method to the registry def w(my_arg): _do_some_magic(my_arg, m) return w run_this_method = FunDecorator() #Create class instance to be used as decorator @run_this_method def method_with_custom_name(my_arg): return "The args is: " + my_arg #do some magic with each decorated method: for m in run_this_method.registry: print(m.__name__) 。像这样:

angular
  .module('SaunaDoorCalc', [])
  .controller('SaunaDoorCalcController', function($scope, $http) {

    $scope.sizeswitch = [           
      { label: 'Стандартный', value: 'standard'},
      { label: 'Нестандартный', value: 'special'}
    ];
    $scope.selectedSizeSwitch = $scope.sizeswitch[0].label; // initial value

    $scope.standardsizes = [           
      { label: '585х1880', price:5600 },
      { label: '685x1880', price:3600 },
      { label: '685x1980', price:5600 },
      { label: '685x2080', price:5600 },
      { label: '685x2180', price:6600 },
      { label: '785x1880', price:5600 },
      { label: '785x1980', price:5600 },
      { label: '785x2080', price:5600 },
      { label: '785x2180', price:6600 }
    ];
    $scope.selectedStandardSize = $scope.standardsizes[1];

    .....

     if ($scope.selectedSizeSwitch == $scope.sizeswitch[0].label) {
         $scope.doorsize = $scope.selectedSizeSwitch + ', ' + $scope.selectedStandardSize.label;
     } else {
         $scope.doorsize = $scope.selectedSizeSwitch + ', ' + $scope.DoorSizeB + 'x' + $scope.DoorSizeH;
              }

    $scope.submit = function(isValid) {
      if (isValid) {
          $http.post($scope.url, 
            {
              "calcname": "saunadoor", 
              "doorsize": $scope.doorsize,            
              .......  // other variables from my form
            }).
                        success(function(data, status) {
                            console.log(data);
                            $scope.status = status;
                            $scope.data = data;
                            $scope.result = data; 
                        });
              $scope.name = null;
              $scope.tel = null;
              $scope.email = null;
              $scope.msg = null;
              $scope.DoorSizeB = null;
              $scope.DoorSizeH = null;
              $scope.calculator.$setPristine();
              $scope.message = 'Заказ отправлен. В ближайшее время мы с вами свяжемся.'; 

            }else{
              $scope.message = 'Заполните обязательные поля формы!'; 
            }

        }


  });

答案 1 :(得分:1)

如果我理解你的问题(如何装饰一个名字未知的方法?)那么这完全有可能。

@decorator
def foo(bar):
  pass

的合成糖
def foo(bar):
  pass
foo = decorator(foo)

所以在你的情况下你应该这样做:

method_with_custom_name = run_this_method(method_with_custom_name)

但是,您提供的示例令人困惑。你为什么不知道method_with_custom_name的名字?它就在那里。它被称为method_with_custom_name。要稍后使用装饰版本,只需调用method_with_custom_name。