retain values between fun calls

G

Gary Wessle

Hi

the second argument in the functions below suppose to retain its value
between function calls, the first does, the second does not and I
would like to know why it doesn't? and how to make it so it does?

thanks

# it does
def f(a, L=[]):
L.append(a)
return L
print f('a')
print f('b')


# it does not
def f(a, b=1):
b = a + b
return b
print f(1)
print f(2)
 
G

George Sakkis

Gary said:
Hi

the second argument in the functions below suppose to retain its value
between function calls, the first does, the second does not and I
would like to know why it doesn't? and how to make it so it does?

thanks

# it does
def f(a, L=[]):
L.append(a)
return L
print f('a')
print f('b')


# it does not
def f(a, b=1):
b = a + b
return b
print f(1)
print f(2)

It's a FAQ:
http://www.python.org/doc/faq/general/#why-are-default-values-shared-between-objects.

Whenever you want to control one or more objects beyond the lifetime of
a single function call, your first thought should be to use a class to
couple behaviour with state:

class SomeFancyClassName(object):
def __init__(self, b=1):
self.b = b
def f(self, a):
self.b += a
return self.b

x = SomeFancyClassName()
print x.f(1)
print x.f(2)


HTH,
George
 
K

Kent Johnson

George said:
Gary said:
Hi

the second argument in the functions below suppose to retain its value
between function calls, the first does, the second does not and I
would like to know why it doesn't? and how to make it so it does?

thanks

# it does
def f(a, L=[]):
L.append(a)
return L
print f('a')
print f('b')


# it does not
def f(a, b=1):
b = a + b
return b
print f(1)
print f(2)

It's a FAQ:
http://www.python.org/doc/faq/general/#why-are-default-values-shared-between-objects.

Whenever you want to control one or more objects beyond the lifetime of
a single function call, your first thought should be to use a class to
couple behaviour with state:

class SomeFancyClassName(object):
def __init__(self, b=1):
self.b = b
def f(self, a):
self.b += a
return self.b

x = SomeFancyClassName()
print x.f(1)
print x.f(2)

If you make the class callable you can match the original syntax:
In [40]: class F(object):
....: b=1
....: def __call__(self, a):
....: F.b += a
....: return F.b
....:
....:

In [41]: f=F()

In [42]: f(1)
Out[42]: 2

In [43]: f(2)
Out[43]: 4

Alternately you can use an attribute of the function to save the state:

In [35]: def f(a):
....: f.b += a
....: return f.b
....:

In [36]: f.b=1

In [37]: f(1)
Out[37]: 2

In [38]: f(2)
Out[38]: 4

Kent
 
B

bruno at modulix

Gary said:
Hi

the second argument in the functions below suppose to retain its value
between function calls, the first does, the second does not and I
would like to know why it doesn't?

Fisrt thing to remember is that function's default args are eval'd only
once - when the def block is eval'd, which is usually at import time.
# it does
def f(a, L=[]):
L.append(a)

Here, you are modifying the (list) object bound to local name L.
return L
print f('a')
print f('b')


# it does not
def f(a, b=1):
b = a + b

And here, you are *rebinding* the local name b to another object.
Understand that modifying an object in-place and rebinding a name are
two really different operations...
return b
print f(1)
print f(2)
and how to make it so it does?

The Q&D solution is to wrap :

def f(a, b = [1])
b[0] = b[0] + a
return b[0]

But this is really a hack - it's ok for a throw-away script, but may not
be the best thing to do in a more serious piece of software.

The clean solution to maintain state between calls is to use a custom
class - hopefully, Python is OO enough to let you write your own callables:

class MyFunc(object):
def __init__(self, initstate=1):
self._state = default
def __call__(self, a):
self._state += a
return self._state

f = MyFunc(1)
print f(1)
print f(2)

HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,297
Messages
2,571,529
Members
48,241
Latest member
PorterShor

Latest Threads

Top