How "list" is implemented in Python?
python - Find a value in a list - Stack Overflow
python - Fastest way to check if a value exists in a list - Stack Overflow
How to use Python 'in' operator to check my list/tuple contains each of the integers 0, 1, 2? - Stack Overflow
Videos
Lately finding myself looking around in builtins.py file trying to learn/understand how the language works. Today I was reading about lists and how they work and etc. And as usually I end up in a class list in builtins.py file. I am now surprised that all the functions of list class is empty. For example, method append has 'pass' in it. And that is it.
Here is a code:
class list(object):
"""
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
"""
def append(self, *args, **kwargs): # real signature unknown
""" Append object to the end of the list. """
pass
def clear(self, *args, **kwargs): # real signature unknown
""" Remove all items from list. """
pass
def copy(self, *args, **kwargs): # real signature unknown
""" Return a shallow copy of the list. """
passI wonder how this works? Why all methods are empty?
As for your first question: "if item is in my_list:" is perfectly fine and should work if item equals one of the elements inside my_list. The item must exactly match an item in the list. For instance, "abc" and "ABC" do not match. Floating point values in particular may suffer from inaccuracy. For instance, 1 - 1/3 != 2/3.
As for your second question: There's actually several possible ways if "finding" things in lists.
Checking if something is inside
This is the use case you describe: Checking whether something is inside a list or not. As you know, you can use the in operator for that:
3 in [1, 2, 3] # => True
Filtering a collection
That is, finding all elements in a sequence that meet a certain condition. You can use list comprehension or generator expressions for that:
matches = [x for x in lst if fulfills_some_condition(x)]
matches = (x for x in lst if x > 6)
The latter will return a generator which you can imagine as a sort of lazy list that will only be built as soon as you iterate through it. By the way, the first one is exactly equivalent to
matches = filter(fulfills_some_condition, lst)
in Python 2. Here you can see higher-order functions at work. In Python 3, filter doesn't return a list, but a generator-like object.
Finding the first occurrence
If you only want the first thing that matches a condition (but you don't know what it is yet), it's fine to use a for loop (possibly using the else clause as well, which is not really well-known). You can also use
next(x for x in lst if ...)
which will return the first match or raise a StopIteration if none is found. Alternatively, you can use
next((x for x in lst if ...), [default value])
Finding the location of an item
For lists, there's also the index method that can sometimes be useful if you want to know where a certain element is in the list:
[1,2,3].index(2) # => 1
[1,2,3].index(4) # => ValueError
However, note that if you have duplicates, .index always returns the lowest index:......
[1,2,3,2].index(2) # => 1
If there are duplicates and you want all the indexes then you can use enumerate() instead:
[i for i,x in enumerate([1,2,3,2]) if x==2] # => [1, 3]
If you want to find one element or None use default in next, it won't raise StopIteration if the item was not found in the list:
first_or_default = next((x for x in lst if ...), None)
7 in a
Clearest and fastest way to do it.
You can also consider using a set, but constructing that set from your list may take more time than faster membership testing will save. The only way to be certain is to benchmark well. (this also depends on what operations you require)
As stated by others, in can be very slow for large lists. Here are some comparisons of the performances for in, set and bisect. Note the time (in second) is in log scale.

Code for testing:
import random
import bisect
import matplotlib.pyplot as plt
import math
import time
def method_in(a, b, c):
start_time = time.time()
for i, x in enumerate(a):
if x in b:
c[i] = 1
return time.time() - start_time
def method_set_in(a, b, c):
start_time = time.time()
s = set(b)
for i, x in enumerate(a):
if x in s:
c[i] = 1
return time.time() - start_time
def method_bisect(a, b, c):
start_time = time.time()
b.sort()
for i, x in enumerate(a):
index = bisect.bisect_left(b, x)
if index < len(a):
if x == b[index]:
c[i] = 1
return time.time() - start_time
def profile():
time_method_in = []
time_method_set_in = []
time_method_bisect = []
# adjust range down if runtime is too long or up if there are too many zero entries in any of the time_method lists
Nls = [x for x in range(10000, 30000, 1000)]
for N in Nls:
a = [x for x in range(0, N)]
random.shuffle(a)
b = [x for x in range(0, N)]
random.shuffle(b)
c = [0 for x in range(0, N)]
time_method_in.append(method_in(a, b, c))
time_method_set_in.append(method_set_in(a, b, c))
time_method_bisect.append(method_bisect(a, b, c))
plt.plot(Nls, time_method_in, marker='o', color='r', linestyle='-', label='in')
plt.plot(Nls, time_method_set_in, marker='o', color='b', linestyle='-', label='set')
plt.plot(Nls, time_method_bisect, marker='o', color='g', linestyle='-', label='bisect')
plt.xlabel('list size', fontsize=18)
plt.ylabel('log(time)', fontsize=18)
plt.legend(loc='upper left')
plt.yscale('log')
plt.show()
profile()
Using the in keyword is a shorthand for calling an object's __contains__ method.
>>> a = [1, 2, 3]
>>> 2 in a
True
>>> a.__contains__(2)
True
Thus, ("0","1","2") in [0, 1, 2] asks whether the tuple ("0", "1", "2") is contained in the list [0, 1, 2]. The answer to this question if False. To be True, you would have to have a list like this:
>>> a = [1, 2, 3, ("0","1","2")]
>>> ("0","1","2") in a
True
Please also note that the elements of your tuple are strings. You probably want to check whether any or all of the elements in your tuple - after converting these elements to integers - are contained in your list.
To check whether all elements of the tuple (as integers) are contained in the list, use
>>> sltn = [1, 2, 3]
>>> t = ("0", "2", "3")
>>> set(map(int, t)).issubset(sltn)
False
To check whether any element of the tuple (as integer) is contained in the list, you can use
>>> sltn_set = set(sltn)
>>> any(int(x) in sltn_set for x in t)
True
and make use of the lazy evaluation any performs.
Of course, if your tuple contains strings for no particular reason, just use(1, 2, 3) and omit the conversion to int.
if ("0","1","2") in sltn
You are trying to check whether the sltn list contains the tuple ("0","1","2"), which it does not. (It contains 3 integers)
But you can get it done using #all() :
sltn = [1, 2, 3] # list
tab = ("1", "2", "3") # tuple
print(all(int(el) in sltn for el in tab)) # True
in uses the method __contains__. Each container type implements it differently. For a list, it uses linear search. For a dict, it uses a hash lookup.
Python Wiki states that val in list has O(n) average time complexity. This implies linear search. I expect list.index(val) to be the same.
After all, list is, well, a list. If you want hash tables, consider using set or dict.