'Python in vs ==. Which to Use in this case?
I am making an AJAX call and passing variable pub in it which could be 1 or 0.
As a beginner I want to be double sure of the variable type that is coming in. I am aware I can easily convert to int() and the problem is actually not with AJAX result but it led to this question.
My code:
if pub == 1 or pub == '1':
#execute funcA()
But the above is not so pythonic for me so I tried:
if pub in [1,'1']:
#execute funcA()
Which of the above code is better in terms of:
- Performance(speed).
- Best practice.
- Memory usage.
Solution 1:[1]
Performance: in is better
timeit.timeit("pub='1'; pub == 1 or pub == '1'")
0.07568907737731934
timeit.timeit("pub='1'; pub in[1, '1']")
0.04272890090942383
timeit.timeit("pub=1; pub == 1 or pub == '1'")
0.07502007484436035
timeit.timeit("pub=1; pub in[1, '1']")
0.07035684585571289
#other options
timeit.timeit("pub='1'; pub in (1,'1')")
0.04643988609313965
timeit.timeit("pub='1'; pub in {1,'1'}")
0.17076611518859863
timeit.timeit("pub=1; pub in (1,'1')")
0.047419071197509766
timeit.timeit("pub=1; pub in {1,'1'}")
0.1770930290222168
So, {} > or > [] > () based on performance.
Practice: in is preferred as it is less to type. (), [], {} equally good based on practice
Memory:
sys.getsizeof([1,"1"])
88
sys.getsizeof("1",1)
38
#other options
sys.getsizeof(("1",1))
72
sys.getsizeof({"1",1})
232
So, {} > [] > () > or based on memory
Although not asked,, good to know:
Functionality: Value equality and not reference equality
in is just sequential checking equality ==. So similar. in uses == and not is.
What I mean to say is this:
>>> a = [1,2,3]
>>> b = [1,a]
>>> b
[1, [1, 2, 3]]
>>> 1 in b
True
>>> a in b
True
>>> [1,2,3] in b
True
So it is implemented not like this:
>>> for i in b:
... print [1,2,3] is i
...
False
False
is will return True if two variables point to the same object, == if the objects referred to by the variables are equal. in uses ==
Solution 2:[2]
This code is better
if pub in [1,'1']:
#execute funcA()
because it's slightly faster but mainly because it is not redundant. The variable pub appears only once there.
Solution 3:[3]
So performance wise in is better :
timeit.timeit("pub='1'; pub == 1 or pub == '1'")
0.16224503758795805
timeit.timeit("pub='1'; pub in[1, '1']")
0.13723585976354258
timeit.timeit("pub=1; pub == 1 or pub == '1'")
0.07986264585216674
timeit.timeit("pub=1; pub in[1, '1']")
0.07246544186018866
And as per memory space the if is better since list uses slightly more memory
sys.getsizeof([1,"1"])
44
sys.getsizeof(1)
12
sys.getsizeof("1")
22
sys.getsizeof("1",1)
22
This is due to the fact that when even empty list is created it takes memory space
sys.getsizeof([])
36
I don't know about the best practice aspect
For me the most pythonic way would be is to use in since it reduces the typing
Solution 4:[4]
1. Performance:
>>> timeit.timeit("pub=1; pub == 1 or pub == '1'", number=10000)
0.0017161369323730469
>>> timeit.timeit("pub=1; pub in[1, '1']", number=10000)
0.0013611316680908203
2. Best Practice: It's good to write programme in a pythonic way I prefer (pub in [1, '1'])
3. Memory Usage: number 1 and string '1' is always cached in python, you can verify the refcount for these objects. So ideally it won't take any extra memory.
>>> sys.getrefcount(1)
833
>>> sys.getrefcount('1')
16
If you use list that needs more memory needs to be allocated to refer these cached objects. (below is in 64 bit type)
>>> sys.getsizeof([1, '1'])
88
These 88 bytes of memory you are gonna allocate extra than the other way of doing.
I would suggest to go with :
if pub in [1,'1']:
#execute funcA()
Solution 5:[5]
In speed:in is faster and by a lot.
To prove it, here is the code.
from datetime import datetime
start0 = datetime.now()
pub = 1
if pub == 1 or pub == '1':
# execute funcA()
pass
end0 = datetime.now() - start0
print end0
start1 = datetime.now()
if pub in [1, '1']:
# execute funcA()
pass
end1 = datetime.now() - start1
print end1
print end0 - end1
Output:
0:00:00.000045
0:00:00.000007
0:00:00.000038
In space:
== is a whole lot better.in takes O(2) space while == takes O(1) space
According to me, the best practice is using in since it is a lot faster and saves a lot of typing
Solution 6:[6]
Not really true. If you switch the order you would see different result, just put in order below:
pub = 1
if pub in [1, '1']:
# execute funcA()
pass
end1 = datetime.now() - start1
print end1
print end0 - end1
start0 = datetime.now()
if pub == 1 or pub == '1':
# execute funcA()
pass
end0 = datetime.now() - start0
print end0
start1 = datetime.now()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | dlask |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | |
| Solution 6 | Alex |
