Typeerror: 'int' Object is not iterable

Asked

Viewed 544 times

0

def add_divisors(list_num):
    final_list = []
    for number in list_num:
        final_list.append([number])
    
    for sublist in final_list:
        for number in sublist:
            for x in range(1, number + 1):
                if number % x == 0:
                    sublist.extend(x)
            
    return final_list


print(add_divisors([3, 4, 6]))

I’m trying to make a function that takes a list of numbers, and returns small lists containing all the divisors of the number. But I’m getting the following error:

Traceback (most recent call last):
  File "<string>", line 16, in <module>
File "<string>", line 11, in add_divisors
TypeError: 'int' object is not iterable
  • 2

    The method extend only accepts eternal objects as argument and you are passing x, that’s kind int. The problem is there as far as I can see.

  • The program loops when it finds a number that is divisible by x 'cause it keeps on increasing itself sublist with the same value indefinitely. You may want to remove or comment on the line sublist.append(x)

  • For it to be in sublist once it returns final_list ???

1 answer

3


The problem, as they say, is that you’re using extend, which receives an iterable and adds all the elements of this in the list. But you are passing a number, which is not iterable. Then you should use append to add the element.

Only you modify the list sublist in the same loop that iterates on it, and that’s never a good idea (read here, here and here to better understand).

Anyway, it sounds to me like you’re complicating the code for nothing. If you want to create a list containing sub-lists, and each sub-list contains the divisors of a number, you could do so:

def add_divisors(list_num):
    final_list = []
    for number in list_num:
        sublist = []
        for x in range(1, number + 1):
            if number % x == 0:
                sublist.append(x)
        final_list.append(sublist)
    return final_list

print(add_divisors([3, 4, 6])) # [[1, 3], [1, 2, 4], [1, 2, 3, 6]]

Of course that’s the naive approach, you don’t need to make a loop up to the number, can go to its square root. And you can start from 2, because every number is divisible by 1, so why test 1? Put it straight on the list. The same goes for the number itself.

And for every splitter you find, you actually found - potentially - two splitters. For example, if the number is 100 and you find the divisor 2, you have also found the divisor 50 (result of 100 / 2). Then just insert both, saving an iteration of the loop. Just take care for the case of perfect squares, not to count the same divisor twice (for example, if the number is 100, we cannot use this logic with the divisor 10, otherwise it will be counted twice).

Then it would look like this:

from math import sqrt

def add_divisors(list_num):
    final_list = []
    for number in list_num:
        divisores = [ 1 ] # é divisor de qualquer número
        for x in range(2, int(sqrt(number)) + 1):
            divisao, resto = divmod(number, x)
            if resto == 0:
                divisores.append(x)
                if x != divisao:
                    divisores.append(divisao)
        divisores.append(number) # todo número é divisor de si mesmo
        final_list.append(divisores)
    return final_list

Although it was "with more lines", it makes fewer iterations than if it was from 1 to the number (of course for small values it won’t make so much difference, but anyway).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.