Mr.Python Mr.Python - 3 months ago 12
Python Question

How to get the type of a varible

I created a function that took a list as a parameter and removed either a space or a number. Code below:

def cleaner(List, filter_out=' '):
if filter_out == ' ':
for i in List:
if i == ' ':
List.remove(' ')
if filter_out == 'int':
for i in List:
if type(i) == int:
List.remove(i)


I tested it using a list like so:

myList = ['h' ' ', 'g', 1, 2, 3, 4, 5, 'p']
print(cleaner(myList, filter_out='int'))


I expected to get
['h' ' ', 'g', 'p']

but instead printed out
['h ', 'g', 2, 4, 'p']

Why did it leave the
1
and
2
? I thought that it would filter out all numbers in the list.

Answer

Removing items from a list while iterating it results in bad consequences:

>>> nums = [1, 2, 3, 4]
>>> for x in nums:
...     print x
...     nums.remove(x)
... 
1
3

You start at index 0. You print nums[0], 1. You then remove it. The next index is 1. Well, [nums[1] is 3 because now the list is [2, 3, 4]. You print that, and remove it. The list is now [2, 4], and you are at the third index. Since nums[2] does not exist, the loop ends, skipping two numbers. What you should do is take advantage of the builtin functions:

myList = ...
myList = filter(lambda x: not isinstance(x, int), myList)

For the example of ' ', it would be:

myList = ...
myList = filter(str.strip, myList)

or

myList = filter(lambda x: x != ' ', myList)

Note: The Python 3 filter() function returns a filter object, not a list. That makes it more efficient if you are just iterating, but if you truly need a list, you can use list(filter(...)).

All of these make a copy of the list instead of doing their work in place. If you want it in place, use myList[:] = ... instead of myList = ... (in the filter() line). Note that a Python 3 filter object does not need to be converted to a list for this to work.

Comments