User Name Password Register
DaniWeb IT Discussion Community
All
What is DaniWeb IT Discussion Community?
You're currently browsing the Python section within the Software Development category of DaniWeb, a massive community of 456,529 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 2,754 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our Python advertiser: Programming Forums
Views: 1113 | Replies: 3
Reply
Join Date: Oct 2007
Posts: 2
Reputation: slunk is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
slunk slunk is offline Offline
Newbie Poster

Default arguments - what is Python doing?

  #1  
Oct 5th, 2007
I began to learn about Python perhaps an hour or two ago.

In a Python tutorial, I came across the below text (between lines of equal signs) regarding default function arguments.

This makes no sense to me at all.

What is the scope and lifetime of L? It appears that the scope is within function f, and the lifetime is permanent?

Well, I'll quit trying to suggest all the possibilities. I simply can't think of any kind of implementation that would cause the first version of the function f below to "accumulate" values, while the second version does not accumulate them.

What is happening under the hood? It seems to me that any reasonable implemenation would cause both versions of f to have the same behavior.




===========================================

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

This will print


[1]
[1, 2]
[1, 2, 3]

If you don't want the default to be shared between subsequent calls, you can write the function like this instead:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

=============================================
AddThis Social Bookmark Button
Reply With Quote  
Join Date: Oct 2004
Posts: 2,529
Reputation: vegaseat will become famous soon enough vegaseat will become famous soon enough 
Rep Power: 11
Solved Threads: 178
Moderator
vegaseat's Avatar
vegaseat vegaseat is offline Offline
DaniWeb's Hypocrite

Re: Default arguments - what is Python doing?

  #2  
Oct 5th, 2007
Just remember that the first time a function is invoked/called, its code gets loaded
into memory. If you give an argument a default that is mutable, you have to be aware of how that will behave. In practice, most of the time you won't do a default with a mutable.

Sort of behaves like a static variable in C. Some folks look at that as a nice feature, others as a "gotcha".
May 'the Google' be with you!
Reply With Quote  
Join Date: Oct 2007
Posts: 2
Reputation: slunk is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
slunk slunk is offline Offline
Newbie Poster

Re: Default arguments - what is Python doing?

  #3  
Oct 6th, 2007
Thanks for your thoughts, Vegaseat.

Actually, on further thought:

It appears to me that the issue is whether the value assigned to the function argument is a value (fundamental type) or a reference (to an object).

Apparently, if a the default value of a function argument is an object, when the function is called for the first time, the object is created and initialized, and the argument variable is assigned a reference to the object.

When the function exits, the object continues to persist.

On subsequent calls to the function, the argument variable is simply assigned a reference to the previously created object.

BY CONTRAST

A statement such as:
L = []

Also creates and initializes an object, and assigns a reference to that object to the variable L.

However, when the function exits, that object is destructed.
Reply With Quote  
Join Date: Jul 2006
Posts: 562
Reputation: jrcagle is on a distinguished road 
Rep Power: 4
Solved Threads: 72
jrcagle jrcagle is offline Offline
Posting Pro

Re: Default arguments - what is Python doing?

  #4  
Oct 6th, 2007
It appears to me that the issue is whether the value assigned to the function argument is a value (fundamental type) or a reference (to an object).

Exactly so, except for the wording.

replace "value (fundamental type)" with "immutable object"
replace "a reference (to an object)" with "mutable object"

All items in Python are objects, and all variables are handled via references.

Apparently, if a the default value of a function argument is an object, when the function is called for the first time, the object is created and initialized, and the argument variable is assigned a reference to the object.

When the function exits, the object continues to persist.

On subsequent calls to the function, the argument variable is simply assigned a reference to the previously created object.

Sort of. Consider:

  1.  
  2. # in a file
  3. class Tmp(object):
  4. print "Hello!"
  5.  
  6. def myfunc(a = Tmp(), b="hi there"):
  7. return a
  8.  
  9. # now run the file
  10. >>>
  11. Hello!
  12. >>> c = myfunc()
  13. >>> a
  14.  
  15. Traceback (most recent call last):
  16. File "<pyshell#42>", line 1, in -toplevel-
  17. a
  18. NameError: name 'a' is not defined
  19. >>> c
  20. <__main__.Tmp object at 0x00B84A10>
  21. >>>

Actually, in all cases, when the function is *loaded*, the default object is created and initialized. That's why running the code above produces 'Hello!' on output even *before* myfunc gets called.

Then, c gets assigned a reference to the object a in myfunc; the reference 'a' goes out of scope (hence the error), but the object itself persists (referred to by c).

BTW, the default argument b never gets assigned, but because it's a part of the myfunc code, it persists also.

So now consider this:

  1. >>> def append(L=[],item=None):
  2. L.append(item)
  3. return L
  4. # L gets created when I hit Enter here, before append is called.
  5. >>> append()
  6. [None] # L is modified here
  7. >>> append()
  8. [None, None]
  9. >>> append(L=[1,2,3]) # A different reference is passed, so default is ignored
  10. [1, 2, 3, None]
  11. >>> append() # Back to the default.
  12. [None, None, None]
  13. >>>

What happens is that the default object is sitting around in memory. Because it is mutable, the function is able to modify it persistently. Contrast:

  1. >>> def append2(s ="", c=""):
  2. s = s+c
  3. return s
  4. >>> append2(c="3")
  5. '3'
  6. >>> append2(c="3")
  7. '3'
  8. >>> append2(c="3")
  9. '3'
  10. >>>

Here, the line s=s+c has the effect of clobbering s. First, the string s + c gets created elsewhere in memory. Then, s gets assigned the reference to the new string. That reference is then returned.

But the original object "" is still sitting around in memory, just as with append() above. So on re-entry, s gets re-assigned to that object, and the result is shown above.

What immutability means for strings is that there are no string methods that can actually change the string itself. Thus, any operation on strings will create a new copy in memory and clobber the reference. That's why string methods, in general, return a copy of the modified string.

By contrast, list methods, in general, return None and instead modify the list in place.

This is Python's subtle way of enforcing the distinction between immutable and mutable objects.

Practical bottom line: DONT USE MUTABLE OBJECTS AS DEFAULT ARGUMENTS UNLESS YOU REALLY WANT THE SIDE EFFECT.

Hope it helps,
Jeff
Reply With Quote  
Reply

Only community members can participate in forum threads. You must register or log in to contribute.

DaniWeb Python Marketplace
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)

 

Thread Tools Display Modes

Similar Threads
Other Threads in the Python Forum

All times are GMT -4. The time now is 4:23 am.
Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC