具有相同主体的多个条件

时间:2020-04-30 22:25:34

标签: python python-3.x

如何在同一主体的Python代码中进行多次检查,以避免违反DRY?

例如,我需要在Django项目中进行检查:

if not obj.name == instance.name:
   post_response('CHANGED')
if not obj.address == instance.address:
   post_response('CHANGED')
if not obj.phone_number == instance.phone_number:
   post_response('CHANGED')
if not obj.postal_code == instance.postal_code:
   post_response('CHANGED')

我还有多个条件要执行。感觉很多余,因为每个条件操作中的主体都是相同的。

4 个答案:

答案 0 :(得分:1)

由于您在两个对象上检查了相同的属性,因此可以像这样动态地比较它们:

attributes = ['name', 'address', 'phone_number', 'postal_code']

for attribute in attributes:
    if not getattr(obj, attribute) == getattr(instance, attribute):
        post_response('CHANGED')
        break

答案 1 :(得分:0)

您可以将测试与andor之类的逻辑运算结合使用。

if not (
        obj.name == instance.name and 
        obj.address == instance.address and 
        obj.phone_number == instance.phone_number and 
        obj.postal_code == instance.postal_code):
   post_response('CHANGED')

但这并不等同于您的代码,因为您使用了多个if而不是elif,因此您的构造可能会触发多次,而只会触发一次。您可以通过计算差异的数量来做到这一点,然后在预期的行为上以该数量执行操作。

changes = sum([
    obj.name != instance.name,
    obj.address != instance.address, 
    obj.phone_number != instance.phone_number,
    obj.postal_code != instance.postal_code])
for _ in range(changes):
   post_response('CHANGED')

但是再说一次,您可能要考虑是否这样做会牺牲太多可读性,因为在这里您需要知道可以将布尔值加在一起,并且range(0)不等于迭代,而您的方法可以直接理解。

答案 2 :(得分:0)

好吧,Python Doc中有一个内置函数叫做getattr()

getattr Documentation

其中一个接受str类型的两个参数,一个是获取属性的对象,另一个是属性名称。

因此,对于这个问题,您可以使用要检查的属性名称创建一个列表/元组,并在for循环中对其进行迭代:

attrNames = ('name', 'address', 'phone_numbers', 'postal_code')


for name in attrName:
if not getattr(obj, name) == getattr(instance, name):
     post_response('CHANGED')

答案 3 :(得分:-1)

这似乎表明您已成功遵守DRY。每行清楚地定义了一个独特的条件,并导致封装了代码的函数。 DRY是指函数的内容,而不是是否在多个位置调用该函数。您正在做的事情似乎完全正确。

如果您在每种情况下都写了几行,并且每个块包含相同的行,则可能违反了DRY。