suppressing import errors

Chris Kaynor ckaynor at zindagigames.com
Tue Nov 15 17:22:21 EST 2011


On Tue, Nov 15, 2011 at 1:34 PM, Chris Angelico <rosuav at gmail.com> wrote:
> On Wed, Nov 16, 2011 at 8:20 AM, David Riley <fraveydank at 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
>



More information about the Python-list mailing list