递归函数返回的列表被截断并且默认为空列表参数

时间:2018-07-10 12:05:13

标签: python python-3.x

我试图找到一个数字的所有主要除数。我正在尝试不传递空列表作为参数。

我可以在没有空列表参数的情况下调用函数podz,但是结果不正确-这是第一个问题-为什么? 我在podzb函数中得到了正确的结果,但是有必要提供空列表参数。

代码:

def podz(x, lista = ()):
    # xa = []
    lis = list(lista)
    # lis = list(lista) # czemu to psuje wynik? jak odpalić krok po kroku?
    # print(lis)
    for i in range(2, x + 1):
        # print(f'x: {x}')
        # print(f'i: {i}')
        # print(f'lis: {lis}')
        if x % i == 0:
            lis.append(i)
            # print(f'lis2: {lis}')
            podz(int(x / i), lis)
            break
    return(lis)

def podzb(x, lista = ()):
    # xa = []
    lis = lista
    # lis = list(lista) # czemu to psuje wynik? jak odpalić krok po kroku?
    # print(lis)
    for i in range(2, x + 1):
        # print(f'x: {x}')
        # print(f'i: {i}')
        # print(f'lis: {lis}')
        if x % i == 0:
            lis.append(i)
            # print(f'lis2: {lis}')
            podzb(int(x / i), lis)
            break
    return(lis)


a = podz(50, [])
print(f'a: {a}')
aa = podz(50)
print(f'aa: {aa}')

a2 = podzb(50, [])
print(f'a2: {a2}')
# aa = podzb(50)        #this causes: AttributeError: 'tuple' object has no attribute 'append'
# print(f'aa: {aa}')

5 个答案:

答案 0 :(得分:1)

AttributeError的原因是默认参数是一个空元组(),而不是一个空列表[]。现在,您可以选择不使用空列表作为various reasons的默认参数,但是由于您要对该对象进行突变,因此确实需要一个列表。

解决方案是做类似的事情

def podzb(x, lista=None):
    if lista is None:
        lista = []
    ... # rest of function

答案 1 :(得分:1)

执行时:

lis = list(lista)

您复制列表。因此,您无需修改​​它。

答案 2 :(得分:1)

podz中,这里:

lis = list(lista)

您根据lista的内容创建一个新列表。然后,您在此处进行递归调用时传递此新列表:

   if x % i == 0:
        lis.append(i)
        # print(f'lis2: {lis}')
        podz(int(x / i), lis)

因此,在递归调用中,您将再次创建一个新列表并将其追加到列表中,然后在递归调用返回时丢弃此新列表,并且由于递归调用在第一个列表的副本上起作用,因此第一个列表是也不更新。

要执行此操作,您必须将递归调用的结果添加到第一个列表中:

   if x % i == 0:
        lis.append(i)
        # print(f'lis2: {lis}')
        lis.extend(podz(int(x / i), lis))

第二个版本(podzb)不会复制该列表,因此它是由所有递归调用更新的同一列表。

答案 3 :(得分:0)

这是因为您从未更新过除数列表,而是将其传递给随后的函数调用,在该函数中创建了一个新列表(然后返回),但从未捕获过返回值。实际上,您根本不需要tuple / list参数,您可以简单地计算并返回函数中的除数,例如:

def podz(x):
    div = []
    for i in range(2, x + 1):
        if x % i == 0:
            div.append(i)
            div.extend(podz(int(x / i)))
            break
    return div

答案 4 :(得分:0)

您的代码有点混乱。 这是给您的更干净的代码:

def divisors(num):
    divisors = []
    for divisor in range(2, num + 1):
        if num % divisor == 0 and isPrime(divisor):
            divisors.append(divisor)
    return divisors

def isPrime(num):
    for divisor in range(2, num):
        if num % divisor == 0: return False
    return True

a = divisors(50)
print(f'a: {a}')