【问题标题】:Recursive function with for loop in PythonPython中带有for循环的递归函数
【发布时间】:2018-05-24 05:36:18
【问题描述】:

我正在尝试在 Python 中执行递归函数来让所有父母从给定的孩子开始 - 例如。如果我想找到从 A 开始的所有父母 - A 有父母 B 和 C,B 有父母 D 和 E,C 有父母 F 和 G,所以函数应该返回集合:{B,C,D,E,F, G} 我有一个 GenTree 类,我将所有人保存在 self.people 中(实例,而不是名称)和一个 Person 类,它有方法 get_parents() 来返回 False 或父母元组(Person 类的 2 个实例)

这是包含类和方法的整个文件:

class Person:
    def __init__(self, name, gender, education, father = False, mother = False):
        self.name = name
        self.gender = gender
        self.education = education
        self.father = father
        self.mother = mother
        self.children = []
    def add_parent(self, inst):
        if inst.gender=="m":
            self.father = inst
        else:
            self.mother = inst
    def add_child(self, inst):
        self.children.append(inst)
    def has_parent(self):
        return True if self.father or self.mother else False
    def get_parents(self):
        if self.has_parent():
            if self.father and self.mother: return self.father, self.mother
            if self.father and not self.mother: return self.father
            if self.mother and not self.father: return self.mother
        else:
            return ()

class GenTree:
    def __init__(self):
        self.people = {}
    def load_from_file(self, file_name):
        data = open(file_name, "r")
        people = {}
        reading = "person"
        for line in data:
            line = line.rstrip()
            reading = "fam" if line=="" else reading
            if reading=="person":
                thisInfo = line.split(";")
                thisName = thisInfo[0]
                thisGender = thisInfo[1]
                thisEd = thisInfo[2]
                self.people[thisName] = Person(thisName, thisGender, thisEd)
            else:
                if line == "":
                    continue
                thisInfo = line.split("=>")
                for i in range(len(thisInfo)):
                    thisInfo[i] = thisInfo[i].rstrip()
                    thisInfo[i] = thisInfo[i].strip(" ")
                self.people[thisInfo[1]].add_parent(self.people[thisInfo[0]])
                self.people[thisInfo[0]].add_child(self.people[thisInfo[1]])

    def get_all_parents(self, child_name):
        child = self.people[child_name]
        parents = child.get_parents()
        if parents:
            for parent in parents:
                return parents + self.get_all_parents(parent.name)
        return parents

g = GenTree()
g.load_from_file("data_a")
print([i.name for i in g.get_all_parents('Katka')])

这是包含给定数据的文件:

Ales;m;c
Alexandr;m;c
Anna;f;h
Dana;f;e
Daniela;f;u
David;m;u
Hana;f;h
Jana;f;u
Jarda;m;c
Jindra;m;u
Jirka;m;u
Jitka;f;h
Juraj;m;u
Karel;m;e
Katka;f;c
Lenka;f;h
Leon;m;h
Leona;f;c
Leos;m;e
Lida;f;e
Ludmila;f;h
Magdalena;f;c
Matej;m;u
Michaela;f;h
Michal;m;e
Patricia;f;h
Petr;m;h
Richard;m;e
Sasa;f;u
Stefan;m;h
Tereza;f;h
Tomas;m;e
Vaclav;m;e
Vojtech;m;c
Zdena;f;e
Zdenek;m;h

Ales        => Zdenek
Tereza      => Zdenek
Alexandr    => Vojtech
Zdena       => Vojtech
David       => Anna
Sasa        => Anna
Jarda       => Daniela
Patricia    => Daniela
Vojtech     => Jindra
Daniela     => Jindra
Zdenek      => Jirka
Anna        => Jirka
Vaclav      => Juraj
Michaela    => Juraj
Ales        => Ludmila
Tereza      => Ludmila
Ludmila     => Magdalena
Juraj       => Magdalena
Juraj       => Tomas
Anna        => Tomas
Zdenek      => Lida
Sasa        => Lida
Lida        => Leona
Zdenek      => Leona
Tomas       => Stefan
Anna        => Stefan
Tomas       => Karel
Leona       => Karel
Tomas       => Leos
Leona       => Leos
Tomas       => Lenka
Leona       => Lenka
Juraj       => Matej
Lenka       => Matej
Juraj       => Leon
Anna        => Leon
Juraj       => Richard
Lenka       => Richard
Richard     => Petr
Ludmila     => Petr
Petr        => Michal
Dana        => Michal
Stefan      => Dana
Anna        => Dana
Michal      => Hana
Lida        => Hana
Michal      => Jana
Lida        => Jana
Petr        => Jitka
Dana        => Jitka
Jirka       => Katka
Dana        => Katka

现在,“print([i.name for i in g.get_all_parents('Katka')])”应该返回:

{'Jirka', 'Dana', 'Zdenek', 'Anna', 'Stefan', 'Ales', 'Tereza', 'David', 'Sasa', 'Tomas', 'Juraj', 'Vaclav', 'Michaela'}

但它会返回

['Jirka', 'Dana', 'Zdenek', 'Anna', 'Ales', 'Tereza']

但它总是只对 for 循环中的第一个执行“self.get_all_parents(parent.name)” 另外,我不知道如何将它作为一个集合返回(我尝试做 get_all_parents(self, child_name, allparents=set()),但它似乎并没有在每次调用函数时重置 allparents 集合)

【问题讨论】:

  • 您的示例不可执行,因此不可验证。发布执行您的功能所需的尽可能多的代码(但不是更多)。
  • 请发布您的树样例或GenTree 的代码。
  • 我不能把它说得很简短,但我现在试图摆脱任何无用的东西。我用代码编辑了帖子
  • 忽略您在循环中使用返回的其他内容。一个函数在返回时结束,因此您的 for 循环被完全忽略

标签: python function recursion


【解决方案1】:

在大多数情况下,使用带有递归的 for 循环并不是一个好主意。实际上它们是一回事。 Haskell(函数式编程语言)没有for循环

def get_all_parents(self, child_name):
        child = self.people[child_name]
        parents = child.get_parents()
        if parents:
            return parents + self.get_all_parents(parent[0].name) + self.get_all_parents(parent[1].name)

        return parents

简单的递归调用意味着调用自身一次或多次

return parents + self.get_all_parents(parent[0].name) + self.get_all_parents(parent[1].name)

这里 get_all_parents 将在它的位置返回它的值 + ....

编辑

在特殊情况下,您可以在此处使用 for 循环。但是这种编码可能非常令人困惑且难以推理

def get_all_parents(self, child_name , ret = ()):
    child = self.people[child_name]
    parents = child.get_parents()
    if parents:
        for p in parents:
            ret = self.get_all_parents(p.name , ret)
    return parents + ret
                

在这种情况下,我们需要一个额外的对象在每次调用之间传输并将结果添加到它。它类似于所有函数调用之间的共享对象。 你可以轻松翻个列表来设置这个问题已经回答了看看How to construct a set out of list items in python?

【讨论】:

  • 我之前尝试过,它可以工作,但我怎样才能将它作为一组返回?
  • 这是另一个问题,如果您想将列表设置为设置,它将删除所有重复的名称。你确定要这样做吗?
  • 是的,这就是重点,返回没有重复名称的集合:)
  • 另外,如果每个人有不同数量的孩子,我会如何为孩子做这样的事情?我不能 return children + self.get_all_children(children[0]) + self.get_all_children(children[1]) 等,因为有人有 1 个孩子,有人有 3 个孩子。我能想到的唯一解决方案是 for 循环,但如何?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 2011-05-07
  • 1970-01-01
  • 2015-07-14
  • 1970-01-01
相关资源
最近更新 更多