Is there any ways we can detect if an object is list in python using type(obj) --> list.
But how can we detect if the object is list of list of the form as:
[['a','b']['a','b'][][]]
Use isinstance() to check for a specific type:
>>> isinstance([], list)
True
Use all() to test if all elements are of a certain type:
all(isinstance(elem, list) for elem in list_of_lists)
all() short-circuits; if any of the tests returns False, the loop is terminated and False is returned. Only if all but one element returns True does all() need to examine every element of the iterable.
If you want to make sure that every item in your list is a list, you could do something like this:
if all(isinstance(i, list) for i in lst):
# All of the items are lists
isinstance(i, list) is the better way of writing type(i) == type(list) or type(i) == list).
all() returns True if all of the items in the sequence are True. It'll return False if any aren't True.
Related
Just wondering the following:
print [()] == list(tuple()) # prints False
The first is a list containing an empty tuple, the second is an empty list.
Why this code prints False instead of True (same result in python 2 and 3)?
Thanks in advance!
You compared a list with one element (an empty tuple) with an empty list. list(tuple()) does not do what you think it does.
That's because list(object) does not produce a list with that one object as an element. list() converts the object, which must be iterable, to a list. It copies the elements out of the object:
>>> dictionary = {'foo': 'bar'}
>>> list(dictionary) # iteration over a dictionary produces keys
['foo']
You gave it an empty tuple, so the result is an empty list:
>>> empty = ()
>>> list(empty)
[]
tuple() does the same thing, by the way. And both list() and tuple() without an argument produce an empty object.
I did some google searching on how to check if a string has any elements of a list in it and I found this bit of code that works:
if any(i in string for i in list):
I know this works, but I don't really know why. Could you share some insight?
As the docs for any say:
Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
So, this is equivalent to:
for element in (i in string for i in list):
if element:
return True
return False
… which is itself effectively equivalent to:
for i in list:
element = i in string
if element:
return True
return False
If you don't understand the last part, first read the tutorial section on list comprehensions, then skip ahead to iterators, generators, and generator expressions.
If you want to really break it down, you can do this:
elements = []
for i in list:
elements.append(i in string)
for element in elements:
if element:
return True
return False
That still isn't exactly the same, because a generator expression builds a generator, not a list, but it should be enough to get you going until you read the tutorial sections.
But meanwhile, the point of having any and comprehensions and so on is that you can almost read them as plain English:
if any(i in string for i in list): # Python
if any of the i's is in the string, for each i in the list: # pseudo-English
i in string for i in list
This produces an iterable of booleans indicating whether each item in list is in string. Then you check whether any item in this iterable of bools is true.
In effect, you're checking whether any of the items in the list are substrings of string.
What's going on here with:
if any(i in string for i in list):
is best explained by illustrating:
>>> xs = ["Goodbye", "Foo", "Balloon"]
>>> s = "Goodbye World"
>>> [i in s for i in xs]
[True, False, False]
>>> any([i in s for i in xs])
True
If you read the any documentaiton you'll note:
any(iterable) Return True if any element of the iterable is true.
If the iterable is empty, return False. Equivalent to:
The list comprehension should be more obvious as it constructs a list of i in s for each element of xs.
Basically (in English) you are returning any match where each sub-string exists in the search string (haystack).
It's important to note as well that any() will short circuit and end on the first True(ish) value it finds. any() can be implement in pure Python like this:
def any(iterable):
for x in iterable:
if x:
return True
return False
a script is feeding me with list of list of list or list of list.
What I plan to do is call this
test = myList[0][0][0]
and if an exception is raised I'll know that it's a list of list.
Is there a better/proper way to do this?
Thanks.
I'm not sure if it's better/proper, but you can also test whether something is a list with isinstance or type functions.
For example
a = [1,2,3]
b = (1,2,3) # Not a list
type(a) == type([]) # True
type(b) == type([]) # False
type(a) is list # True
type(b) is list # False
isinstance(a, list) # True
isinstance(b, list) # False
The first method is probably not ideal, the second would probably be better if you were to use type, but I think the general consensus is that isinstance is generally better.
EDIT: Some discussion about the difference between the two approaches
So, I guess your code would look something like:
if(isinstance(myList[0][0], list)):
# Use myList[0][0][0]
else:
# Use myList[0][0]
Given a list xs and a value item, how can I check whether xs contains item (i.e., if any of the elements of xs is equal to item)? Is there something like xs.contains(item)?
For performance considerations, see Fastest way to check if a value exists in a list.
Use:
if my_item in some_list:
...
Also, inverse operation:
if my_item not in some_list:
...
It works fine for lists, tuples, sets and dicts (check keys).
Note that this is an O(n) operation in lists and tuples, but an O(1) operation in sets and dicts.
In addition to what other have said, you may also be interested to know that what in does is to call the list.__contains__ method, that you can define on any class you write and can get extremely handy to use python at his full extent.
A dumb use may be:
>>> class ContainsEverything:
def __init__(self):
return None
def __contains__(self, *elem, **k):
return True
>>> a = ContainsEverything()
>>> 3 in a
True
>>> a in a
True
>>> False in a
True
>>> False not in a
False
>>>
I came up with this one liner recently for getting True if a list contains any number of occurrences of an item, or False if it contains no occurrences or nothing at all. Using next(...) gives this a default return value (False) and means it should run significantly faster than running the whole list comprehension.
list_does_contain = next((True for item in list_to_test if item == test_item), False)
The list method index will return -1 if the item is not present, and will return the index of the item in the list if it is present. Alternatively in an if statement you can do the following:
if myItem in list:
#do things
You can also check if an element is not in a list with the following if statement:
if myItem not in list:
#do things
There is also the list method:
[2, 51, 6, 8, 3].__contains__(8)
# Out[33]: True
[2, 51, 6, 3].__contains__(8)
# Out[33]: False
There is one another method that uses index. But I am not sure if this has any fault or not.
list = [5,4,3,1]
try:
list.index(2)
#code for when item is expected to be in the list
print("present")
except:
#code for when item is not expected to be in the list
print("not present")
Output:
not present
Basically my question is say you have an list containing 'None' how would you try retrieving the sum of the list. Below is an example I tried which doesn't work and I get the error: TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'. Thanks
def sumImport(self):
my_list = [[1,2,3,None],[1,2,3],[1,1],[1,1,2,2]]
k = sum(chain.from_iterable(my_list))
return k
You can use filter function
>>> sum(filter(None, [1,2,3,None]))
6
Updated from comments
Typically filter usage is filter(func, iterable), but passing None as first argument is a special case, described in Python docs. Quoting:
If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.
Remove None (and zero) elements before summing by using filter:
>>> k = sum(filter(None, chain.from_iterable(my_list)))
>>> k
20
To see why this works, see the documentation for filter:
filter(function, iterable)
Construct a list from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If iterable is a string or a tuple, the result also has that type; otherwise it is always a list. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.
Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)] if function is not None and [item for item in iterable if item] if function is None.
Another suggestion:
from itertools import chain
k = sum(x for x in chain.from_iterable(my_list) if x)
Assuming you want to treat None as zero, a simple way is
sum(x if x is not None else 0 for x in chain.from_iterable(my_list))
Explicitly, this is equivalent to filter:
k = sum([x for x in chain.from_iterable(my_list) if x])
That saves me from remembering another function. :P
You always have the option of just writing the loop you want:
k = 0
for sublist in my_list:
for val in sublist:
if val is not None:
k += val
But it certainly doesn’t hurt to know about filter either.
Just using sum and map:
sum(map(lambda x: x or 0, [1,2,3,None]))
# 6