更清洁的方式来表示Python中的规则(if-else)

时间:2015-03-31 21:38:58

标签: python business-rules

我正在尝试找到一种设计模式(或maybe an algorithm),它将帮助我以更清洁的方式编写这些规则。有什么建议吗?

def get_rules(user, value):
    if 500 <= value < 5000 and not user.address:
        return [REQUEST_ADDRESS]

    if value >= 5000:
        if not user.address and not user.phone:
            return [REQUEST_ADDRESS, REQUEST_PHONE]
        if user.address and not user.phone:
            return [REQUEST_PHONE]
        if not user.address and user.phone:
            return [REQUEST_ADDRESS]

    # Potentially ~20 more conditions here based on various attributes of user
    return [STATES.REQUEST_NONE]

注意:我不是在寻找规则引擎,因为我不想通过在python中添加“业务友好”DSL来使我的代码复杂化。 Python本身是编写这些规则的简单语言。

有趣的阅读:http://martinfowler.com/bliki/RulesEngine.html(但我仍然试图远离“框架”为我做这件事。)

4 个答案:

答案 0 :(得分:2)

在这种情况下你可以使用dict:

resdict = {(False, False): [REQUEST_ADDRESS, REQUEST_PHONE],
           (True, False): [REQUEST_PHONE],
           (False, True): [REQUEST_ADDRESS]}
return resdict[(user.address, user.phone)]

您还可以使用列表理解:

return [req for req, haveit in zip([REQUEST_ADDRESS, REQUEST_PHONE], [user.address, user.phone]) if not haveit]

或者更简单的列表附加:

res = []
if not user.address:
    res.append(REQUEST_ADDRESS)
if not user.phone:
    res.append(REQUEST_PHONE)

答案 1 :(得分:2)

你正在检查许多不同的组合,你的“如果a而不是b,则检查不是a而b检查不是a而不是b”策略,以确定你需要发送的请求组合。

相反,只检查你缺少的东西:

missing = []
if not user.phone:
    missing.append(REQUEST_PHONE)
if not user.address:
    missing.append(REQUEST_ADDRESS)

return missing or [REQUEST_NONE]

答案 2 :(得分:0)

如果我理解正确的问题,那么您有一个用户属性列表。如果一个为假,则应将REQUEST值添加到列表中。那么这可能会有所帮助:

# define all your combinations here:
mapping = {'address': REQUEST_ADDRESS, 'phone': REQUEST_PHONE, …)

return [value for key, value in mapping.items()
        if not getattr(user, key, None)]

答案 3 :(得分:0)

看起来像你的规则&#34;归结为:请求对象user中不作为属性出现的字段的值。我将假设属性到请求的映射可以是任意的;您可以将其表示为字典映射,例如像这样:

rulemap = { 
      "address": REQUEST_ADDRESS, 
      "phone": REQUEST_PHONE, 
      # etc.
    }

然后,您可以通过检查rulemap中哪些键不作为对象user中的属性来获取要发出的请求列表:

return [ rulemap[fld] for fld in rulemap.keys() if fld not in user.__dict__ ]