<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
David Perlman wrote:
<blockquote cite="mid:132718BC-6D08-4B18-9453-A3335F3F5E68@wisc.edu"
 type="cite">OK, I thought I had this one fixed but it was weirder than
I thought.&nbsp; I think I understand what's going on, but I wanted to check
with the experts here.
  <br>
  <br>
I have the following class definition, which does not subclass
anything:
  <br>
  <br>
class oneStim:
  <br>
&nbsp;&nbsp;&nbsp; def __init__(self, time, mods=[], dur=None, format='%1.2f'):
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.time=time
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.mods=mods
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.dur=dur
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.format=format
  <br>
  <br>
&nbsp;&nbsp;&nbsp; def __cmp__(self,other):
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return cmp(self.time,other.time)
  <br>
  <br>
&nbsp;&nbsp;&nbsp; def __repr__(self):
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timestr=self.format % self.time
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.mods == []:
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; modstr=''
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; modstr = '*' + ','.join(self.format % i for i in self.mods)
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.dur == None:
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; durstr = ''
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; durstr = ':' + (self.format % self.dur)
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return timestr + modstr + durstr
  <br>
  <br>
&nbsp;&nbsp;&nbsp; def __len__(self):
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return len(self.__repr__())
  <br>
  <br>
  <br>
&gt;&gt;&gt; a=oneStim(40)
  <br>
&gt;&gt;&gt; a
  <br>
40.00
  <br>
&gt;&gt;&gt; a.mods.append(3)
  <br>
&gt;&gt;&gt; a
  <br>
40.00*3.00
  <br>
&gt;&gt;&gt; a.dur=10
  <br>
&gt;&gt;&gt; a
  <br>
40.00*3.00:10.00
  <br>
&gt;&gt;&gt; a.mods.append(1)
  <br>
&gt;&gt;&gt; a
  <br>
40.00*3.00,1.00:10.00
  <br>
  <br>
So far so good, that's exactly what it's supposed to do.&nbsp; But now look:
  <br>
  <br>
&gt;&gt;&gt; b=oneStim(50)
  <br>
&gt;&gt;&gt; b
  <br>
50.00*3.00,1.00
  <br>
  <br>
The mods that were added to the first instance of oneStim also appear
in the second, newly created instance!
  <br>
  <br>
It appears that what is happening here is that the __init__() method is
being parsed by the interpreter once at initial run, and at that time
the statement "mods=[]" is being parsed, which means that the [] object
is being instantiated once there at the beginning.&nbsp; So every
instantiation of class oneStim ends up sharing a reference to the same
list object, instead of each one having its own.
  <br>
  <br>
I fixed this by changing it to "mods=None" and then setting it in the
body of the __init__ method.&nbsp; Works fine now.
  <br>
  <br>
My question is, is this just a quirky misbehavior, or is there a
principled reason why the code I have shown above only instantiates the
empty list in the arguments once?
  <br>
</blockquote>
<br>
RTFM: (Reference Manual, 7.6 Function definitions)<br>
....<br>
<strong>Default parameter values are evaluated when the function
definition is executed.</strong> This means that the expression is
evaluated once, when the function is defined, and that that same
``pre-computed'' value is used for each call. This is especially
important to understand when a default parameter is a mutable object,
such as a list or a dictionary: if the function modifies the object
(e.g. by appending an item to a list), the default value is in effect
modified. This is generally not what was intended. A way around this is
to use <code>None</code> as the default, and explicitly test for it in
the body of the function, e.g.:
<p></p>
<div class="verbatim">
<pre>def whats_on_the_telly(penguin=None):
    if penguin is None:
        penguin = []
    penguin.append("property of the zoo")
    return penguin
</pre>
</div>
<blockquote cite="mid:132718BC-6D08-4B18-9453-A3335F3F5E68@wisc.edu"
 type="cite"><br>
Thanks for any insight.&nbsp; As I said, I got it to work fine now, so this
isn't critical, but I'm curious to understand why things work the way
they do.&nbsp; :)
  <br>
  <br>
--
  <br>
-dave----------------------------------------------------------------
  <br>
"Pseudo-colored pictures of a person's brain lighting up are
  <br>
undoubtedly more persuasive than a pattern of squiggles produced by a
  <br>
polygraph.&nbsp; That could be a big problem if the goal is to get to the
  <br>
truth."&nbsp; -Dr. Steven Hyman, Harvard
  <br>
  <br>
  <br>
  <br>
_______________________________________________
  <br>
Tutor maillist&nbsp; -&nbsp; <a class="moz-txt-link-abbreviated" href="mailto:Tutor@python.org">Tutor@python.org</a>
  <br>
To unsubscribe or change subscription options:
  <br>
<a class="moz-txt-link-freetext" href="http://mail.python.org/mailman/listinfo/tutor">http://mail.python.org/mailman/listinfo/tutor</a>
  <br>
  <br>
</blockquote>
<br>
<br>
<div class="moz-signature">-- <br>
Bob Gailer<br>
Chapel Hill NC<br>
919-636-4239</div>
</body>
</html>