Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Strange Behavior (http://www.velocityreviews.com/forums/t395290-strange-behavior.html)

abcd 10-16-2006 02:26 PM

Strange Behavior
 
class Foo:
def __init__(self, name, data=[]):
self.name = name
self.data = data

def addData(self, val):
self.data.append(val)


f = Foo('a')
f.addData(1)
f.addData(2)

f2 = Foo('b')

print f.name, f.data
print f2.name, f2.data

----------------------------
OUTPUT
---------------------------
a [1, 2]
b [1, 2]


.....why would f and f2 contain the same data??

however, if I do this instead....

f = Foo('a')
f.addData(1)
f.addData(2)

f2 = Foo('b', [])

print f.name, f.data
print f2.name, f2.data

----------------------------
OUTPUT
---------------------------
a [1, 2]
b []


Any ideas? is this a bug?


Rob Williscroft 10-16-2006 02:31 PM

Re: Strange Behavior
 
abcd wrote in news:1161008763.124120.147010@i3g2000cwc.googlegro ups.com in
comp.lang.python:

> class Foo:
> def __init__(self, name, data=[]):


http://docs.python.org/ref/function.html#l2h-619

Rob.
--
http://www.victim-prime.dsl.pipex.com/

abcd 10-16-2006 02:40 PM

Re: Strange Behavior
 
Rob Williscroft wrote:
> http://docs.python.org/ref/function.html#l2h-619



thanks. weird that it works that way since they even state "This is
generally not what was intended."

oh well.


Steven D'Aprano 10-16-2006 02:51 PM

Re: Strange Behavior
 
On Mon, 16 Oct 2006 07:26:05 -0700, abcd wrote:

> class Foo:
> def __init__(self, name, data=[]):


The binding of the name "data" to the empty list happens at compile time,
not runtime.

> self.name = name
> self.data = data
>
> def addData(self, val):
> self.data.append(val)


Every time you call addData on an instance, it appends to the same list.
So all instances created with Foo(name) share the same list in data.

Think of it like this:

some_list = []
x = Foo("fred", some_list)
y = Foo("wilma", some_list)

Isn't it obvious now that both instances share the same list? That x.data
and y.data don't just have the same value, but are the same object? The
same thing happens when you set the default.


> f = Foo('a')
> f.addData(1)
> f.addData(2)
>
> f2 = Foo('b', [])


And in this case, you've passed a DIFFERENT empty list as an argument.


The normal Python way for handling this situation is to not use mutable
objects as defaults unless you want this behaviour. Instead, use None as
the default value:

class Foo:
def __init__(self, name, data=None):
self.name = name
if data is None: self.data = []
else: self.data = data


> Any ideas? is this a bug?


Well, it's a bug in your code :)

It isn't a bug in Python. At worst, it is a "gotcha", but it is a
deliberate design decision, and quite useful. For example, this is good
for caching complicated calculations:

def function(x, _cache={}):
# _cache is initialised to an empty dictionary at compile time
if _cache.has_key(x):
return _cache[x]
else:
# complicated and time consuming calculation happens
_cache[x] = result
return result




--
Steven.


Paul Rubin 10-16-2006 03:04 PM

Re: Strange Behavior
 
Steven D'Aprano <steve@REMOVE.THIS.cybersource.com.au> writes:
> It isn't a bug in Python. At worst, it is a "gotcha", but it is a
> deliberate design decision, and quite useful. For example, this is good
> for caching complicated calculations:
>
> def function(x, _cache={}):
> # _cache is initialised to an empty dictionary at compile time
> if _cache.has_key(x):
> return _cache[x]


The above can be done explicitly:

def function(x):
if function._cache.has_key(x):
return function._cache[x]
...
# function gets an initially-empty cache
function._cache = {}

So the existing behavior, while not a bug (since it's documented), may
well be a wart.

Neil Cerutti 10-16-2006 03:09 PM

Re: Strange Behavior
 
On 2006-10-16, Steven D'Aprano
<steve@REMOVE.THIS.cybersource.com.au> wrote:
> Well, it's a bug in your code :)
>
> It isn't a bug in Python. At worst, it is a "gotcha", but it is
> a deliberate design decision, and quite useful. For example,
> this is good for caching complicated calculations:


I'd say the feature is "usable" rather than "useful", like
bitfields in C.

--
Neil Cerutti
Next Sunday Mrs. Vinson will be soloist for the morning service.
The pastor will then speak on "It's a Terrible Experience."
--Church Bulletin Blooper

Fredrik Lundh 10-16-2006 04:01 PM

Re: Strange Behavior
 
Steven D'Aprano wrote:

> It isn't a bug in Python. At worst, it is a "gotcha", but it is a
> deliberate design decision, and quite useful. For example, this is good
> for caching complicated calculations:


it's also used to pass in *objects* instead of names into an inner scope.

</F>


Diez B. Roggisch 10-16-2006 04:42 PM

Re: Strange Behavior
 
abcd wrote:

> Rob Williscroft wrote:
>> http://docs.python.org/ref/function.html#l2h-619

>
>
> thanks. weird that it works that way since they even state "This is
> generally not what was intended."


The "not intended" refers to the programmer making the mistake of creating a
shared instance - which usually isn't intended, as you yourself are an
example of.

Diez

Carsten Haese 10-16-2006 05:10 PM

Re: Strange Behavior
 
On Mon, 2006-10-16 at 10:51, Steven D'Aprano wrote:
> On Mon, 16 Oct 2006 07:26:05 -0700, abcd wrote:
>
> > class Foo:
> > def __init__(self, name, data=[]):

>
> The binding of the name "data" to the empty list happens at compile time,
> not runtime.


I think this statement needs to be clarified. The binding of "data" to
the empty list *does* happen at runtime, not at compile time. However,
the binding happens only once, when the "def" statement is executed, as
opposed to every time the __init__ function is called.

-Carsten



Fredrik Lundh 10-16-2006 05:28 PM

Re: Strange Behavior
 
Carsten Haese wrote:

> I think this statement needs to be clarified. The binding of "data" to
> the empty list *does* happen at runtime, not at compile time. However,
> the binding happens only once, when the "def" statement is executed, as
> opposed to every time the __init__ function is called.


to be precise, it happens every time the "def" statement is executed.

</F>



All times are GMT. The time now is 01:19 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57