On Tue, Nov 15, 2011 at 1:34 PM, Chris Angelico <ros...@gmail.com> wrote: > On Wed, Nov 16, 2011 at 8:20 AM, David Riley <fraveyd...@gmail.com> wrote: >> Comparisons to singletons like None should always be done with >> 'is' or 'is not', never the equality operators. >> >> Also, beware of writing "if x" when you really mean "if x is not None" >> -- e.g. when testing whether a variable or argument that defaults to >> None was set to some other value. The other value might have a type >> (such as a container) that could be false in a boolean context! > > It's probably quicker to execute "if x is None" than "if x" > (presumably the former just compares the two pointers). On the other > hand, it's more compact to leave off the "is None". And on the > gripping hand, neither "quicker to execute" nor "more compact" equates > to "more Pythonic".
I decided to run some tests to see which is faster. As is turns out, in simple cases (eg, True), "if x: pass" is faster than "if x is None: pass" if x is True, and otherwise its the same. If x is a custom type (I only tested a simple custom class written in Python), "if x is None: pass" is significantly faster. Overall, performance-wise, it is irrelevant - use the code that is the most clear in the situation. Only if there is a custom type involved, and then only if that type defines Python code to be executed, does it matter. The tests (the code is shown later - its about 53 lines, with lots of copy+paste...): 1a: 0.04 usec/pass -- if None: pass 1b: 0.03 usec/pass -- if True: pass 1c: 0.27 usec/pass -- if customObjectWithNonZero: pass 1d: 0.04 usec/pass -- if customObjectNoNonZero: pass 2a: 0.04 usec/pass -- if None is None: pass 2b: 0.04 usec/pass -- if True is None: pass 2c: 0.04 usec/pass -- if customObjectWithNonZero is None: pass 2d: 0.04 usec/pass -- if customObjectNoNonZero is None: pass The tests were run on Python 2.6x64 on Windows: 2.6.4 (r264:75706, Aug 4 2010, 17:00:56) [MSC v.1500 64 bit (AMD64)] The code: import timeit def test(): numRuns = 10000000 statement1 = 'if x: pass' statement2 = 'if x is None: pass' setup1 = 'x = None' setup2 = 'x = True' setup3 = ''' class Test(object): def __nonzero__(self): return True x = Test()''' setup4 = ''' class Test(object): pass x = Test()''' t1a = timeit.Timer(stmt=statement1, setup=setup1) t1b = timeit.Timer(stmt=statement1, setup=setup2) t1c = timeit.Timer(stmt=statement1, setup=setup3) t1d = timeit.Timer(stmt=statement1, setup=setup4) t2a = timeit.Timer(stmt=statement2, setup=setup1) t2b = timeit.Timer(stmt=statement2, setup=setup2) t2c = timeit.Timer(stmt=statement2, setup=setup3) t2d = timeit.Timer(stmt=statement2, setup=setup4) a1 = [] b1 = [] c1 = [] d1 = [] a2 = [] b2 = [] c2 = [] d2 = [] for i in xrange(10): a1.append(1000000 * t1a.timeit(number=numRuns)/numRuns) b1.append(1000000 * t1b.timeit(number=numRuns)/numRuns) c1.append(1000000 * t1c.timeit(number=numRuns)/numRuns) d1.append(1000000 * t1d.timeit(number=numRuns)/numRuns) a2.append(1000000 * t2a.timeit(number=numRuns)/numRuns) b2.append(1000000 * t2b.timeit(number=numRuns)/numRuns) c2.append(1000000 * t2c.timeit(number=numRuns)/numRuns) d2.append(1000000 * t2d.timeit(number=numRuns)/numRuns) print "1a: %.2f usec/pass" % (sum(a1) / len(a1),) print "1b: %.2f usec/pass" % (sum(b1) / len(b1),) print "1c: %.2f usec/pass" % (sum(c1) / len(c1),) print "1d: %.2f usec/pass" % (sum(d1) / len(d1),) print "2a: %.2f usec/pass" % (sum(a2) / len(a2),) print "2b: %.2f usec/pass" % (sum(b2) / len(b2),) print "2c: %.2f usec/pass" % (sum(c2) / len(c2),) print "2d: %.2f usec/pass" % (sum(d2) / len(d2),) > > ChrisA > -- > http://mail.python.org/mailman/listinfo/python-list > -- http://mail.python.org/mailman/listinfo/python-list