python `in` operator use cases
Python *in* operator is membership test operator. *Examples:* List ----
In [1]: python_webframeworks = ['flask', 'django', 'pylons', 'pyramid', 'brubeck'] In [2]: 'flask' in python_webframeworks Out[2]: True In [3]: 'web.py' in python_webframeworks Out[3]: False
*in* operator iterates over the list of elements and returns *True* or *False*. *What about nested list?*
In [4]: webframeworks = [['flask', 'django', 'pyramid'],['rails', 'sintara'],['zend', 'symfony']] In [5]: 'flask' in webframeworks Out[5]: False
*in* isnt handy for nested list, unless it is overriden. Dict ---- *in* operator against dictionary checks for the presence of key.
In [7]: person = {'name': 'kracekumar', 'country': 'India', 'os': 'Linux', 'programming_languages': {'web': 'php', 'multi_paradigm': ['python', 'ruby', 'java', 'c#']}} In [8]: 'name' in person Out[8]: True
*in* doesnt check inside key if value is dict
In [9]: 'web' in person Out[9]: False
In case if dict needs to look into keys whose value is dict, you need to override `__contains__`. At the end of the blog post I will explain, now lets create a class which is inherited from dict and try the same experiment.
In [10]: class Person(dict): ....: pass ....: In [11]: p = Person() In [12]: p Out[12]: {} In [13]: p['name'] = 'krace' In [14]: p Out[14]: {'name': 'krace'}
To make things simple `__init__` and other `magic methods` are omitted.
In [15]: 'name' in p Out[15]: True
In [16]: conferences_attended = set(['Pycon - India', 'code retreat', 'JSFOO', 'Meta Refresh']) In [17]: 'Pycon - India' in conferences_attended Out[17]: True
In [18]: 2 in xrange(3) Out[18]: True
In [19]: nested_list = [[1, 3, 5, 7], [2, 4, 6, 8], []] In [20]: [] in nested_list Out[20]: True In [21]: [2, 4, 6, 8] in nested_list Out[21]: True
In case of nested list checking whether inner list is empty is pretty handy. Strings -------
In [23]: message = " Python is simple and powerful programming language " In [24]: "Python" in message Out[24]: True In [25]: message.find("Python") Out[25]: 1 In [26]: message = "Python is simple and powerful programming language " In [27]: message.find("Python") Out[27]: 0
*in* can be used to check the presence of a sequence or substring against string. In other languages there will be function to check for substring, but in python its very straightforward. This is one of the reason why I love Python. **NOTE:** Dont use find method in string to find the existence of a substring because it will return the position.
if message.find(text): #lets do what we need do else: #fall back
Above snippet is wrong since text might be present in the beginning which will result 0 and if condition will fail. Files -----
In [29]: with open('test.txt', 'w') as f: f.write(" some text for checking") ....: In [32]: with open('test.txt', 'r') as f: for text in f: print 'some' in text ....: True
overriding `__contains__` ----
Consider a `class Person` which is inherited from *dict* and override `__contains__`
In [153]: class Person(dict): .....: def __contains__(self, item): .....: for key in self: .....: if key is item: .....: return True .....: else: .....: if isinstance(self[key], dict): .....: for k in self[key]: .....: if k is item: .....: return True .....: else: .....: return False .....: In [154]: p = Person() In [155]: p['skills'] = {'programming_languages': {'web': ['php'], 'multi_paradigm': ['python', 'ruby', 'c#']} } In [156]: 'skills' in p Out[156]: True In [157]: 'programming_languages' in p Out[157]: True In [158]: 'web' in p Out[158]: False
In the above example *key* will be looked for two level dict only.