11

I am noticing the following:

class c:
  def __init__(self, data=[]):
    self._data=data
a=c()
b=c()
a._data.append(1)
print b._data
[1]

Is this the correct behavior?

2

2 Answers 2

14

Yes, it's correct behavior.

However, from your question, it appears that it's not what you expected.

If you want it to match your expectations, be aware of the following:

Rule 1. Do not use mutable objects as default values.

def anyFunction( arg=[] ):

Will not create a fresh list object. The default list object for arg will be shared all over the place.

Similarly

def anyFunction( arg={} ):

will not create a fresh dict object. This default dict will be shared.

class MyClass( object ):
    def __init__( self, arg= None ):
        self.myList= [] if arg is None else arg 

That's a common way to provide a default argument value that is a fresh, empty list object.

Sign up to request clarification or add additional context in comments.

5 Comments

Will never work. is a bit harsh. Won't give you a new empty mutable object on each call, seems a little more balanced. If you know this happens you might actually want to use this behaviour.
@MattH: Reusing the same mutable object via a default value is so odd that it defies finding a sensible use case. It's a default value, so it may (or may not) get used as such depending on the client's use of the interface. It would be so hard to diagnose problems with this that I stand by my original formulation. Especially for n00bz.
You should add an example of how to work around this. Otherwise the answer is good and correct.
There's a sensible use case for almost everything. For mutable default values I'd choose a simple memoization strategy, for example as described by Alex Martelli here: stackoverflow.com/questions/1651154/…
@Scott Griffiths: While there's a use case, I would debate "sensible". Yes, it works, but so does unreadable spaghetti code. Using mutable objects as default values is a bad idea. In the example question, the default value syntax is used to provide a hidden memoization context; it doesn't fit the usual design patterns for "default" because there is o sensible reason to provide a real value.
1

Always make functions like this then:

def __init__ ( self, data = None ):
    if data is None:
       data = []

    self._data = data

Alternatively you could also use data = data or [], but that prevents the user from passing empty parameters ('', 0, False etc.).

3 Comments

Of course you can also do if not data: data = [].
your example data = data or [] works just fine for empty lists being passed. You'd be saying data will be [] or [] so it will look at the first one and see that it evaluates to "false", then it will take the other value.
I know, my point was that when you pass False for example, [] will be used as the value, although you passed False.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.