【问题标题】:Factoring out shared data validation using Python decorators使用 Python 装饰器分解共享数据验证
【发布时间】:2017-02-09 21:28:55
【问题描述】:

我在一个项目的一个类中有以下两个函数:

def stage_changes(self, change_set_name):
    change_set_id = self._get_change_set_id(change_set_name)
    # Perform validation on change set ID
    self._stage_changes_internal(change_set_id)

def commit_changes(self, change_set_name):
    change_set_id = self._get_change_set_id(change_set_name)
    # Perform validation on change set ID (same validation as first function)
    # Perform some other computation using change set ID
    self._commit_changes_internal(change_set_id, ...)

我希望从这些函数中考虑前两条共享行,即

change_set_id = self._get_change_set_id(change_set_name)
# Perform validation on change set ID

我的问题:

  1. 在这里使用装饰器真的有意义吗,还是我在一个我应该只调用简单帮助函数的地方太有创意了?
  2. 如果使用装饰器确实有意义,我将如何构建它?这样做似乎很麻烦,因为我需要在公共结尾中计算的值来在每个函数中执行额外的计算(即共享逻辑不仅仅产生副作用,它返回一个值) .

【问题讨论】:

    标签: python python-decorators


    【解决方案1】:

    正如您所提到的,您可以使用辅助函数应用 DRY 原则。 我认为它更多地是关于个人品味,在这里使用帮助器或装饰器功能。 但作为装饰器,它可能看起来像这样:

    from functools import wraps
    
    def validateData(fn):
        @wraps(fn)
        def wrapper(*args, **kw):
            cls = args[0]
            change_set_name = args[1]
    
            if change_set_name in ('bar', 'foobar'):
                kw['change_set_id'] = 1
            else:
                kw['change_set_id'] = None
    
            return fn(*args, **kw)
        return wrapper
    
    
    class Foo():
        @validateData
        def stage_changes(self, change_set_name, change_set_id=None):
            print('change_set_id in stage_changes:', change_set_id)
            # Perform validation on change set ID
            #self._stage_changes_internal(change_set_id)
    
        @validateData
        def commit_changes(self, change_set_name, change_set_id=None):
            #change_set_id = self._get_change_set_id(change_set_name)
            print('change_set_id in commit_changes:', change_set_id)
            # Perform validation on change set ID (same validation as first function)
            # Perform some other computation using change set ID
            #self._commit_changes_internal(change_set_id, ...)
    
    f = Foo()
    f.stage_changes('bar')
    f.stage_changes('banana')
    

    打印:

    change_set_id in stage_changes: 1
    change_set_id in stage_changes: None
    

    【讨论】:

      猜你喜欢
      • 2020-04-07
      • 2019-07-01
      • 2018-09-28
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 2014-12-25
      • 2012-11-24
      • 2020-03-04
      相关资源
      最近更新 更多