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

Reply via email to