“if” or maybe “=”? What is faster in python?
December 22, 2009 | pythonauthor: Karol Zielinski | comments: 4 | views: 1424
Tags: if, pylons, python, speed, test
We did some tests few days ago. Kind of easy problem, however… it’s not so obvious. What should I do? Check if variable exists or just create this variable without checking it?
Ok, a little description. I’d like to know which piece of code is faster…
some_variable = 'string'
or
if not some_variable:
some_variable = 'string'
I will check it in loop, because only these kind of results would be reliable for me.
So…
First we will check simple built-in type, such as string.
our code:
import datetime
var1 = None
var2 = None
one = 0
two = 0
for i in range(1000):
date1 = datetime.datetime.now()
var1 = 'string'
date2 = datetime.datetime.now()
sub1 = date2 - date1
date1 = None
date2 = None
date1 = datetime.datetime.now()
if not var2:
var2 = 'string'
date2 = datetime.datetime.now()
sub2 = date2 - date1
if sub1 < sub2:
one += 1
elif sub1 > sub2:
two +=1
print one
print two
Result:
181
293
So… these methods have similar speed.
Most of the tests (526) gave us the same time. A bit more effective is the second solution (with ‘if’).
our code:
import datetime
var1 = {}
var2 = {}
var1['dict'] = None
var2['dict'] = None
one = 0
two = 0
three = 0
for i in range(1000):
date1 = datetime.datetime.now()
var1['dict'] = 'string'
date2 = datetime.datetime.now()
sub1 = date2 - date1
date1 = None
date2 = None
date1 = datetime.datetime.now()
if not var2.get('dict'):
var2['dict'] = 'string'
date2 = datetime.datetime.now()
sub2 = date2 - date1
if sub1 < sub2:
one += 1
elif sub1 > sub2:
two +=1
else:
three += 1
print one
print two
print three
Result:
154
20
826
So… these methods have similar speed.
Most of the tests (826) gave us the same time. A bit more effective is the first solution (without ‘if’).
our code:
var1 = {}
var2 = {}
var1['dict'] = None
var2['dict'] = None
one = 0
two = 0
three = 0
for i in range(1000):
date1 = datetime.datetime.now()
var1['dict'] = 'string'
date2 = datetime.datetime.now()
sub1 = date2 - date1
date1 = None
date2 = None
date1 = datetime.datetime.now()
if not var2['dict']:
var2['dict'] = 'string'
date2 = datetime.datetime.now()
sub2 = date2 - date1
if sub1 < sub2:
one += 1
elif sub1 > sub2:
two +=1
else:
three += 1
print one
print two
print three
Result:
15
85
900
So… these methods have similar speed.
Most of the tests (900) gave us the same time. A bit more effective is the second solution (with ‘if’).
our code (with ‘get()’ method):
one = 0
two = 0
three = 0
for i in range(1000):
date1 = datetime.datetime.now()
session['lang'] = 'en'
session.save()
date2 = datetime.datetime.now()
sub1 = date2 - date1
date1 = None
date2 = None
date1 = datetime.datetime.now()
if not session.get('lang'):
session['lang'] = 'en'
session.save()
date2 = datetime.datetime.now()
sub2 = date2 - date1
if sub1 < sub2:
one += 1
elif sub1 > sub2:
two +=1
else:
three += 1
print one
print two
print three
Result:
9
986
5
and the second piece of code (without ‘get()’ method):
one = 0
two = 0
three = 0
for i in range(1000):
date1 = datetime.datetime.now()
session['lang'] = 'en'
session.save()
date2 = datetime.datetime.now()
sub1 = date2 - date1
date1 = None
date2 = None
date1 = datetime.datetime.now()
if not session['lang']:
session['lang'] = 'en'
session.save()
date2 = datetime.datetime.now()
sub2 = date2 - date1
if sub1 < sub2:
one += 1
elif sub1 > sub2:
two +=1
else:
three += 1
print one
print two
print three
Result:
5
993
2
So… both of the sessions’ piece of codes gave us the same result: ‘if’ is much faster
Yes, I know why I have such a results… everything is because of the pylons’ session.save() method. However… the truth is that the solution with ‘if’ won this battle.
Built-in types, integers, strings, etc – solution with ‘if’ is a little bit faster
Dictionary with ‘get()’ method – solution without ‘if’ is a little bit faster
Dictionary without ‘get()’ method – solution with ‘if’ is a little bit faster
Session dictionary (Pylons’ session) – solution with ‘if’ is much faster
Hello, I'm Karol Zielinski, internet evangelist, an entrepreneur, project manager and a web developer from Gdynia, Poland. I like creative design, good advertisement, social media and all kind of stuff around the web.
December 22, 2009, 8:26 am
[...] tech.karolzielinski.com Follow us on Twitter 1,512 śledzących RSS Feed 169 czytelników "i" czy "="? Co jest szybsze w pythonie? 1 głosuj! Kilka dni temu przeprowadziliśmy małe testy. Niby takie proste zagadnienie, a [...]
December 22, 2009, 10:07 am
First of all, your timing method is far from accurate. Try running this:
import timeit
def avg(list):
return sum(list) / len(list)
print avg(timeit.repeat(setup = “a = None”, stmt = “a = ‘string’”, repeat = 100, number = 10**6))
print avg(timeit.repeat(setup = “a = None”, stmt = “if not a: a = ‘string’”, repeat = 100, number = 10**6,))
The “if .. then” statement is a bit slower.
Also, “if not a” doesn’t actually check if the name “a” is defined. Rather is checks if the object referenced under the name “a” has a logical value of “True”.
One way of checking if “a” is defined in local context is to use “if ‘a’ in locals()”. If you can ensure that “a” is always defined, but you want to use None as undefined value, then “if a is None” is the right way.
Example 2: Again, the same problem. Implicit casting result value of get() to a boolean is incorrect and far from efficient. It’s better to write “if ‘name’ in some_dictionary”.
import timeit
def avg(list):
return sum(list) / len(list)
print avg(timeit.repeat(setup = “d = {}”, stmt = “d['a'] = ‘string’”, repeat = 100, number = 10 ** 6))
print avg(timeit.repeat(setup = “d = {}”, stmt = “if ‘a’ not in d: d['a'] = ‘string’”, repeat = 100, number = 10 ** 6,))
The diffrence is now smaller and mainly depends on repeat/number ratio.
Example 3 is insignificant, because d['name'] actually calls d.__getitem__(‘name’) which is almost the same as get(). If you have diffrent results from example 2, it’s the flaw of your timing method
Finally: session.save() does a hell lot of checks and probably some database access. As you wrote yourself, the last test has **nothing** to do with anything you wrote before. Which means that this whole article is pointless.
December 22, 2009, 10:20 am
I reckon this is an example of premature optimization — and I’m usually the first to point out micro-optimizations.
The difference for the if foo:foo=’bar’ is negligible and only serves to obfuscate the code. Its not like the assignment has to copy any data.
The dictionary example could be refined to:
var2.setdefault(‘dict’, ‘string’)
Assuming that it is your intention to set the value if it isn’t already present.
December 22, 2009, 2:09 pm
[...] This post was mentioned on Twitter by Karol Zielinski, Python Talk. Python Talk said: RT @karol_zielinski: “if” or maybe “=”? What is faster in python? http://bit.ly/7hLjMe [...]