A performance issue when using default value

2010-01-31 Thread keakon
I've found strange performance issue when using default value, the
test code is list below:

from timeit import Timer

def f(x):
  y = x
  y.append(1)
  return y

def g(x=[]):
  y = []
  y.append(1)
  return y

def h(x=[]):
  y = x
  y.append(1)
  return y

def f2(x):
  y = x
  y.append(1)
  return y + []

def g2(x=[]):
  y = []
  y.append(1)
  return y + []

def h2(x=[]):
  y = x
  y.append(1)
  return y + []

TIMES = 1
print Timer('f([])','from __main__ import f, g, h').timeit(TIMES)
print Timer('g()','from __main__ import f, g, h').timeit(TIMES)
print Timer('h([])','from __main__ import f, g, h').timeit(TIMES)
print Timer('h()','from __main__ import f, g, h').timeit(TIMES)
print Timer('f2([])','from __main__ import f2, g2, h2').timeit(TIMES)
print Timer('g2()','from __main__ import f2, g2, h2').timeit(TIMES)
print Timer('h2([])','from __main__ import f2, g2, h2').timeit(TIMES)
print Timer('h2()','from __main__ import f2, g2, h2').timeit(TIMES)


I tested it with Python 2.5.4, 2.6.4 and 3.1.1 on Windows XP, and get
almost the same result:
0.00449247041174
0.00439608944712
0.00455867994396
0.00327471787615
0.00791581052899
0.00684919452053
0.00734311204357
0.30974942346

h2() is about 42 times slower than h2([]), but h() is a litter faster
than h([]).

If change TIMES to 2, other results are 2 times than before, but h2
() is 4 times(about 1.2 sec) than before.

Is there any tricks in it?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A performance issue when using default value

2010-01-31 Thread keakon
On 2月1日, 下午1时20分, alex23  wrote:
> alex23  wrote:
> > keakon  wrote:
> > > def h2(x=[]):
> > >   y = x
> > >   y.append(1)
> > >   return y + []
>
> > Are you aware that 'y = x' _doesn't_ make a copy of [], that it
> > actually points to the same list as x?
>
> Sorry, I meant to suggest trying the following instead:
>
> def h2(x=None):
>   if x is None: x = []
>   x.append(1)
>   return x + []
>
> It's a common idiom to use None as a sentinel for this situation, esp.
> where you _don't_ want a default mutable object to be reused.

Thank you, I got it.

The default value is mutable, and can be reused by all each call.
So each call it will append 1 to the default value, that's very
different than C++.
-- 
http://mail.python.org/mailman/listinfo/python-list