[Tutor] strange difference between two functions

Michael Janssen Janssen at rz.uni-frankfurt.de
Mon Dec 15 11:16:08 EST 2003


On Mon, 15 Dec 2003, Hameed Khan wrote:

> hi,
>   i was reading the tutorial comes with python
> documentation. i found 2 example functions in it. but
> i cant understand these functions because of their
> different output. so if any one of you out there can
> tell me why there are giving different outputs just
> because of a if check. that will be very nice of you.
> below is the output directly copied from interactive
> python prompt.
>
>
> # function one #
> >>> # function one
> ... def f(a, L=[]):
> ...     L.append(a)
> ...     return L
> ...
> >>> f(1)
> [1]
> >>> f(2)
> [1, 2]
> >>> f(3)
> [1, 2, 3]
>
>
> # function two #
> >>> # function two
> ... def f2(a, L=[]):
> ...     if not L:
> ...             L = []
> ...     L.append(a)
> ...     return L
> ...
> >>> f2(1)
> [1]
> >>> f2(2)
> [2]
> >>> f2(3)
> [3]
> >>>

The python tutorial (setcion 4.71) claims "The default value is
evaluated only once" and continues with the much more astonishing story
about python mutuable types like lists. "evaluated only once" is
probably better shown this way:

>>> import time
>>> def yet(t=time.time()):
...  return t
...
>>> yet()
1071502070.145452
>>> yet()
1071502070.145452
>>>

--> the current time is evaluated when defining the function and won't
change with subsequents calls of "yet" ("t" doesn't get reevaluated
every time). Further:

>>> yet(111)
111
>>> yet()
1071502070.145452
>>>

---> "yet" will "remember" the original value of "t" (this is what a
function is suppose to do with keyword-arguments...). But where has
this value been remembered? My answere (as a non expert) to this
question is "somewhere deep in machines memory".

Now look at "f" version1:

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


---> "L" is remembered "somewhere deep - and so on". Any call of "f"
*without* an explicit value for "L" will use the value from "somewhere
deep". It will use it and it will append "a" to this value. That's the
story.


How does it work? Python uses (at least it does so in my understanding)
references to object. References are the names like "L", "f" or "yet".
Objects can be lists, functions, strings, anything. One practical reason
for this is: You can rename hugh list by creating another reference (and
not by copiing several MB's in machines memory):

>>> name1 = ["hugh", "...." ,"possibly really hugh"]
>>> name2 = name1 # make a reference from name2 to target of name1
>>> id(name1);id(name2) # both aims to identicall data
1075964268
1075964268

The flipside is, that "name1.append('more stuff')" will show effect on
name2 also (you know already why: name1 and name2 are references to the
same data)

now back to question:

> >>> # function one
> ... def f(a, L=[]):
> ...     L.append(a)
> ...     return L
> ...
> >>> f(1)
> [1]
> >>> f(2)
> [1, 2]
> >>> f(3)
> [1, 2, 3]

---> this shows both: "evaluated only once" and "mutuable types might
change while references stay". It's problably a little hard to
understand, but the good thing is it's very important to understand ;-)
(Feel free to ask further)

But what does f2 do different?

> >>> # function two
> ... def f2(a, L=[]):
> ...     if not L:
> ...             L = []
> ...     L.append(a)
> ...     return L

In case "L" is empty the if-condition is true and "L" gets assigned to a
brand new list: "L = []" creates a new (empty) list and set "L" as a
reference (overwriting old "L"). This way "f2(1)", "f2(2)", and "f2(3)"
starts all with their own brand new list.


Michael



More information about the Tutor mailing list