【发布时间】:2017-01-18 01:52:56
【问题描述】:
以下模型包含两个几乎相同的函数list_ancestors 和list_descendants。什么是只编写一次代码的好方法?
class Node(models.Model):
name = models.CharField(max_length=120, blank=True, null=True)
parents = models.ManyToManyField('self', blank=True, symmetrical=False)
def list_parents(self):
return self.parents.all()
def list_children(self):
return Node.objects.filter(parents=self.id)
def list_ancestors(self):
parents = self.list_parents()
ancestors = set(parents)
for p in parents:
ancestors |= set(p.list_ancestors()) # set union
return list(ancestors)
def list_descendants(self):
children = self.list_children()
descendants = set(children)
for c in children:
descendants |= set(c.list_descendants()) # set union
return list(descendants)
def __str__(self):
return self.name
编辑:从以下答案得出的解决方案:
def list_withindirect(self, arg):
direct = getattr(self, arg)()
withindirect = set(direct)
for d in direct:
withindirect |= set(d.list_withindirect(arg))
return list(withindirect)
def list_ancestors(self):
return self.list_withindirect('list_parents')
def list_descendants(self):
return self.list_withindirect('list_children')
【问题讨论】:
-
@Sayse:我不明白你的问题。祖先是父母的概括,所以
list_ancestors使用list_parents。后代是孩子的概括,所以list_descendants使用list_children。 -
list_ancestors先获取父母,然后递归获取父母的祖先。list_descendants先获取孩子,然后递归获取孩子的后代。由于我尝试统一的这两个相似函数是递归的,所以我的“解决方案”list_withindirect也是递归的。 -
抱歉,我错过了那部分
标签: django methods code-duplication