如何在同一主体的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')
我还有多个条件要执行。感觉很多余,因为每个条件操作中的主体都是相同的。
答案 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)
您可以将测试与and
或or
之类的逻辑运算结合使用。
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()
,
其中一个接受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。