0

(python 2.7.8)

I'm trying to make a function to extract integers from a mixed list. Mixed list can be anything but the e.g. I'm going with is:

testList = [1, 4.66, 7, "abc", 5, True, 3.2, False, "Hello", 7]

I thought this would be simple, and just wrote:

def parseIntegers(mixedList):
    newList = [i for i in mixedList if isinstance(i, int)]
    return newList

Problem is that the newList this creates has boolean values as well as integers, meaning it gets me:

[1, 7, 5, True, False, 7]

Why is that? I also used for loop (for i in mixedList: if isinstace.....), but it's essentially the same(?) and has the same problem.

questions989
  • 159
  • 1
  • 2
  • 9
  • 1
    Use `type(i) == int` instead. – grc Nov 04 '14 at 00:07
  • Be wary of using `type` - this breaks the concept of polymorphism: if someone subclasses `int`, your code will no longer work. – Smashery Nov 04 '14 at 00:14
  • @Smashery It seems that they don't want to include subclasses in this case. – grc Nov 04 '14 at 00:17
  • 1
    Possibly so - but you'd better know what you're doing if you're trying to circumvent the key feature of object-oriented languages (polymorphism). Maybe using `type` *is* the right thing to do. Just be wary is all. – Smashery Nov 04 '14 at 00:23
  • 1
    @Smashery The problem here is that `bool` *is* a subclass of `int` and it is unwanted, so breaking the `isinstance` guideline and using `type` is correct in this case. – SethMMorton Nov 04 '14 at 01:49

4 Answers4

3

as explained by @pts for isinstance, so use type like this

[ x for x in testList if type(x)==int ]

output:

[1, 7, 5, 7]

use set to remove duplication

Hackaholic
  • 19,069
  • 5
  • 54
  • 72
2

Apparently bool is a subclass of int:

Python 2.7.3 (default, Feb 27 2014, 19:58:35) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> isinstance(42, int)
True
>>> isinstance(True, int)
True
>>> isinstance('42', int)
False
>>> isinstance(42, bool)
False
>>> 

Instead of isinstance(i, int), you can use type(i) is int or isinstance(i, int) and not isinstance(i, bool).

pts
  • 80,836
  • 20
  • 110
  • 183
1

The best approach is not to use type, but to use a chain of isinstance calls. The pitfall of using type is that someone could subclass int in the future, and then your code won't work. Also, since you are using Python 2.x, you need to consider numbers greater than or equal to 2^31: these are not ints. You need to consider the long type:

def parseIntegers(mixedList):
    return [x for x in testList if (isinstance(x, int) or isinstance(x, long)) and not isinstance(x, bool)]

Reason for needing to consider long:

>>> a = 2 ** 31
>>> isinstance(a, int)
False
Smashery
  • 57,848
  • 30
  • 97
  • 128
1
testList = [1, 4.66, 7, "abc", 5, True, 3.2, False, "Hello", 7]
print([x for x in testList if isinstance(x,int) and not isinstance(x,bool)])
[1, 7, 5, 7]
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321