"Can only iterable" Python error - python

Hello my fellow programmers.
I am a fairly new programmer, and now I am facing a great predicament. I am getting the error:
can only assign an iterable
Firstly I don't know what that means.
Secondly I will leave my code for you professionals to critique it:
def num_top(int_lis):
duplic_int_lis = int_lis
int_firs= duplic_int_lis [0]
int_lis[:] = duplic_int_lis [int_firs]
Basically I am trying to find the [0] element in the list and then using that int as an index position to find the integer at that index position.

int_lis[:] = duplic_int_lis [int_firs] means assign all the items of duplic_int_lis [int_firs] to int_lis, so it expects you to pass an iterable/iterator on the RHS.
But in your case you're passing it an non-iterable, which is incorrect:
>>> lis = range(10)
>>> lis[:] = range(5)
>>> lis #all items of `lis` replaced with range(5)
[0, 1, 2, 3, 4]
>>> lis[:] = 5 #Non-iterable will raise an error.
Traceback (most recent call last):
File "<ipython-input-77-0704f8a4410d>", line 1, in <module>
lis[:] = 5
TypeError: can only assign an iterable
>>> lis[:] = 'foobar' #works for any iterable/iterator
>>> lis
['f', 'o', 'o', 'b', 'a', 'r']
As you cannot iterate over an integer, hence the error.
>>> for x in 1: pass
Traceback (most recent call last):
File "<ipython-input-84-416802313c58>", line 1, in <module>
for x in 1:pass
TypeError: 'int' object is not iterable

The RHS of a slice-assignment must be an iterable, not a scalar. Consider slice-deleting and then appending instead.

An iterable is a thing with multiple items that you can iterate through (for example: take the 1st value do something, then the 2nd do something, etc...) Lists, dictionaries, tuples, strings have several items in them and can be used as iterables. As a counterexample: number types don't qualify as iterable.
Remember that computers count from #0 so: if you want the first value of a list you can use
my_list[0]
before you go further I would suggest watching this video about looping. https://www.youtube.com/watch?v=EnSu9hHGq5o

Related

What is difference between tuples and lists [duplicate]

This question already has answers here:
What's the difference between lists and tuples?
(22 answers)
Closed 21 days ago.
I am trying to understand the difference between tuples and lists
I was trying to use tuples and lists in a piece of my code, and not realising the difference between tuple and list, could someone please tell me difference,
Thanks,
Gops
Both list and tuple are used to store multiple items within a single collection, but there is a key difference tuple is immutable while list is not. Mutability means the ability to modify the object afterward.
# Here we can modify my_list just fine
>>> my_list = ["hello"]
>>> my_list[0] = "world"
>>> print(my_list)
['world']
# But modifying my_tuple leads to an error
>>> my_tuple = ('hello',)
>>> my_tuple[0] = 'world'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> print(my_tuple)
('h', 'e', 'l', 'l', 'o')
You might think to ask why use tuples at all if we can't mutate them. Wouldn't it be better to just have everything be more flexible?
Well, there are things that tuples can do that lists cannot do such as acting as keys for a dictionary. This is a very useful trick for things like points as keys.
>>> my_dict = {("hello", "world"): "foo"}
>>> my_dict[("hello", "world")]
'foo'
If you try to do the same with lists, you get this error. The error message hints at the key difference. Lists cannot be hashed but tuples can be hashed.
>>> my_dict = {["hello", "world"]: "foo"}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Please specify what is the difference of these two line in python [duplicate]

This question already has answers here:
How are Python in-place operator functions different than the standard operator functions?
(2 answers)
Closed last month.
Declaration
lst = []
What is the difference between these two lines in python why first line is working another is not
lst += 'a' # this line is working
lst = lst + 'a' # but this line is showing error 'can only concatenate list (not "str") to list'
Not understanding why this two statements are giving different results
on a list += is the same as extend. The argument is seen as an iterable. So it iterates on the string and adds it. But it's not correct in the general case, for instance a string with length > 1.
>>> lst = []
>>> lst += "ab"
>>> lst
['a', 'b'] # not what is expected probably
or adding an integer
>>> lst += 0
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: 'int' object is not iterable
On the other hand, in lst + <right term>, the right term is supposed to be a list. Even a tuple would end up with an error.
In your case, the best solution is
lst += ['a']
or
lst.append('a')
which avoids creating a list just to add it to the first one.
As a side note,
lst = lst + other_list
is different from
lst += other_list
as it reassigns lst name on a copy of the old list with added other_list.
Better be aware of that if some other variable is still referencing the old lst
Plus the performance suffers from the copy of the old contents.

Python - List Index Out Of Range In For Loop

I'm fairly new to python and I'm currently working on a program that will encrypt and decrypt strings. As part of it, I need the individual letters of the string to each be added to an empty list; for example, the string 'hello' would be entered into a list list like so:
['h','e','l','l','o']
The part of the code that is giving me this error can be found below. Thanks.
emptyList=[]
message=input("What Would You Like To Encrypt?\n")
messageLength=len(message)
for count in range(0,messageLength):
emptyList=[]
emptyList[count].append(message[count])
You are trying to address indices in an empty list:
>>> lst = []
>>> lst[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> lst[0] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
If you wanted to add elements to a list, just use list.append() directly on the list object itself to create more indices; don't create new empty lists each time:
emptyList=[]
messageLength=len(message)
for count in range(0,messageLength):
emptyList.append(message[count])
Not that you need to be this elaborate, the following is enough:
emptyList = list(message)
list() takes any iterable and adds all the elements of that iterable to a list. Since a string is iterable, producing all the characters in that string, calling list() on a string creates a list of those characters:
>>> list('hello')
['h', 'e', 'l', 'l', 'o']
Basically you want just read from the input and then output a list
Python 2.7
message=raw_input("What Would You Like To Encrypt?\n")
print list(message)
Python 3.X
message=input("What Would You Like To Encrypt?\n")
print(list(message))
Output
If you input Hello
['H', 'e', 'l', 'l', 'o']

Remove an element from list and return the result

I want to generate a list which looks like:
['ret-120','ret-115','ret-110',....'ret-5','ret5',....'ret240']
Please note, there's no ret0 element in the list. So I have to remove it from a list populated by range function. I've tried:
['ret'+str(x) for x in list(range(-120,241,5)).remove(0)]
However this gives out an error:
TypeError: 'NoneType' object is not iterable
Is this possible to accomplish with one line of code?
The simplest way to do what you want is to add a conditional inside your list comprehension:
lst = ['cumRet'+str(x) for x in xrange(-120,241,5) if x != 0]
# This part: ^^^^^^^^^
I also removed the unnecessary list creation and changed range->xrange (note that this range->xrange change is Python2 only)
Your NoneType error is because list.remove(index) modifies in-place, so it returns None.
Hence, you are trying to loop [for x in None].
2-line alternate way (with ;)
tmp = list(range(-120,241,5));tmp.remove(0)
['ret'+str(x) for x in list(range(-120,241,5)).remove(0)]
remove() return None
The list remove() method return None, So 'NoneType' object is not iterable.
Demo:
>>> b = list(range(-120,241,5)).remove(0)
>>> b
>>> print b
None
We will create variable of list and then remove 0 from it.
Demo:
>>> tmp = list(range(-120,241,5))
>>> tmp.remove(0)
>>> ['cumRet'+str(x) for x in tmp]
['cumRet-120', 'cumRet-115', 'cumRet-110', 'cumRet-105', 'cumRet-100', 'cumRet-95', 'cumRet-90', 'cumRet-85', 'cumRet-80', 'cumRet-75', 'cumRet-70', 'cumRet-65', 'cumRet-60', 'cumRet-55', 'cumRet-50', 'cumRet-45', 'cumRet-40', 'cumRet-35', 'cumRet-30', 'cumRet-25', 'cumRet-20', 'cumRet-15', 'cumRet-10', 'cumRet-5', 'cumRet5', 'cumRet10', 'cumRet15', 'cumRet20', 'cumRet25', 'cumRet30', 'cumRet35', 'cumRet40', 'cumRet45', 'cumRet50', 'cumRet55', 'cumRet60', 'cumRet65', 'cumRet70', 'cumRet75', 'cumRet80', 'cumRet85', 'cumRet90', 'cumRet95', 'cumRet100', 'cumRet105', 'cumRet110', 'cumRet115', 'cumRet120', 'cumRet125', 'cumRet130', 'cumRet135', 'cumRet140', 'cumRet145', 'cumRet150', 'cumRet155', 'cumRet160', 'cumRet165', 'cumRet170', 'cumRet175', 'cumRet180', 'cumRet185', 'cumRet190', 'cumRet195', 'cumRet200', 'cumRet205', 'cumRet210', 'cumRet215', 'cumRet220', 'cumRet225', 'cumRet230', 'cumRet235', 'cumRet240']
>>>
Exception Handling:
Best practice to do Exception Handling when we went to remove element from the list because if element not present in the list then it will raise ValueError exception.
Demo:
>>> l = [4,6,8]
>>> l.remove(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>>
>>> try:
... l.remove(3)
... except ValueError:
... print "List not contains remove element."
...
List not contains remove element.
>>>
The problem is that the list.remove() method changes the list in-place and effectively returns None, but you can skip x when it's zero like this:
['ret'+str(x) for x in range(-120, 241, 5) if x]
If you're using Python 2, range() could be changed to xrange() which would avoid creating a temporary list of all the integer values.

Should I use list() or wrap in brackets?

If I have a nested dictionary and I want to make a value into a list and add to it, should I do this
mydict[my_key][my_value] = [mydict[my_key][my_value]].append(new_value)
or this
mydict[my_key][my_value] = list(mydict[my_key][my_value]).append(new_value)
The structure looks like:
{'foo': {'bar': 'hi'}}
and I want:
{'foo': {'bar': ['hi', 'bye']}}
You should not do either one.
list.append works in-place and always returns None. So, mydict[my_key][my_value] will be assigned to None after Python executes either of those lines.
You need to call list.append on its own line:
mydict[my_key][my_value] = [mydict[my_key][my_value]]
mydict[my_key][my_value].append(new_value)
Also, list() and [] are two different things.
Putting mydict[my_key][my_value] in square brackets makes a one-item list where mydict[my_key][my_value] is the item.
Using list() however tells Python to iterate over mydict[my_key][my_value] and collect its items into a list. Moreover, a TypeError will be raised if mydict[my_key][my_value] is not iterable.
Below is a demonstration of what I said above:
>>> tup = (1, 2, 3)
>>> [tup] # Places tup in a list
[(1, 2, 3)]
>>> list(tup) # Makes tup into a list
[1, 2, 3]
>>>
>>> [1]
[1]
>>> list(1) # Integers are not iterable
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>>
If you want a list for each dict element, use `defaultdict``
from collections import defaultdict
mydict = defaultdict(list)
mydict[some_key].append(new_value)

Categories

Resources