以下模型包含两个几乎相同的函数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')
答案 0 :(得分:2)
使用字符串并在对象上调用getattr以获取可调用函数。
def list_withindirect(self, fn1):
direct = getattr(self, fn1)()
withindirect = set(direct)
for d in direct:
withindirect |= set(d.list_withindirect(fn1))
return list(withindirect)
def list_ancestors(self):
return self.list_withindirect('list_parents')
答案 1 :(得分:0)
这似乎是绑定和未绑定方法问题中的问题。
当您最初将self.list_parents
传递给self.list_withindirect(list_direct)
时,一切正常。
但是当你以递归的方式通过时! self.list_parents
到d.list_withindirect
(即后代),您不小心将direct
变量填充到最顶层调用者对象的父级,而不是d
。
例如,可以使用getattr
进行解析,就像 2ps 一样(upd:他的原始代码中的错误在那里的评论中找到)