•
•
•
•
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
![]() |
•
•
Join Date: Oct 2007
Posts: 2
Reputation:
Rep Power: 0
Solved Threads: 0
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:
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:
=============================================
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=============================================
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".
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!
•
•
Join Date: Oct 2007
Posts: 2
Reputation:
Rep Power: 0
Solved Threads: 0
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.
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.
•
•
Join Date: Jul 2006
Posts: 562
Reputation:
Rep Power: 4
Solved Threads: 72
•
•
•
•
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:
Python Syntax (Toggle Plain Text)
# in a file class Tmp(object): print "Hello!" def myfunc(a = Tmp(), b="hi there"): return a # now run the file >>> Hello! >>> c = myfunc() >>> a Traceback (most recent call last): File "<pyshell#42>", line 1, in -toplevel- a NameError: name 'a' is not defined >>> c <__main__.Tmp object at 0x00B84A10> >>>
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:
Python Syntax (Toggle Plain Text)
>>> def append(L=[],item=None): L.append(item) return L # L gets created when I hit Enter here, before append is called. >>> append() [None] # L is modified here >>> append() [None, None] >>> append(L=[1,2,3]) # A different reference is passed, so default is ignored [1, 2, 3, None] >>> append() # Back to the default. [None, None, None] >>>
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:
Python Syntax (Toggle Plain Text)
>>> def append2(s ="", c=""): s = s+c return s >>> append2(c="3") '3' >>> append2(c="3") '3' >>> append2(c="3") '3' >>>
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
![]() |
•
•
•
•
•
•
•
•
DaniWeb Python Marketplace
•
•
•
•
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
- Command-line argument syntax (C++)
- file types and main arguments (C)
- A few questions on classes!.. (C++)
- Count Access to Function (Python)
- Python as a first language (Python)
- starting Python (Python)
- Python Tutorial Release 2.4.1 (Python)
- Accessing a variable of another class (Java)
- A few questions about C++ (C++)
- Interpretation of an instructors C++ program... (C++)
Other Threads in the Python Forum
- Previous Thread: Python bug??? Or just a stupid question?
- Next Thread: Ping in a loop



Linear Mode