4
class Entry():
    def __init__(self,l=[]):
        self.list = l


a = Entry()
b = Entry()
a.list.extend([1,2])
assert a.list!=b.list   #assert error

if using

a = Entry([])
b = Entry([])
a.list.extend([1,2])
assert a.list!=b.list   #right

What's the difference between above two examples?

George Stocker
  • 57,289
  • 29
  • 176
  • 237
liu
  • 937
  • 1
  • 9
  • 15

3 Answers3

3

Consult: "Least Astonishment" and the Mutable Default Argument

But to solve your problem do this:

def __init__(self,l=None):
    self.list = l if l else []

alternatively, as has been suggested by an edit, (which should have been a comment). you can use or:

def __init__(self, l=None):
    self.list = l or []
Inbar Rose
  • 41,843
  • 24
  • 85
  • 131
  • Using def __init__(self,l=list()): not works – liu Oct 21 '13 at 15:05
  • It shouldn't be a problem, but use the second solution I suggested instead then. – Inbar Rose Oct 21 '13 at 15:07
  • 1
    @InbarRose: `l=list()` won't work for the same reason `l=[]` doesn't. The arguments behave as part of the `def`, not part of the function: they're executed once, when the function is declared. – DSM Oct 21 '13 at 15:33
  • Fine, I removed the first solution, just use the second one (the only remaining one). It works fine. – Inbar Rose Oct 21 '13 at 15:36
1

Don't use [] as default parameter.

Use this:

class Entry():
    def __init__(self,l=list()):
        ...

Here the problem is that the same list is assigned to each Entry instance.

So what append is something like this:

lst = []
a = Entry(lst)
b = Entry(lst)

a.list == b.list # lst == lst -> True
user278064
  • 9,982
  • 1
  • 33
  • 46
1

This is because in the first case, you pass a default argument [ ], which references the same list object.

    class Entry():
        def __init__(self,l=[]):
        self.list = l

    a = Entry()
    b = Entry()
    a.list.extend([1,2])
    print a.list, b.list # [1, 2] [1, 2]
    print id(a.list), id(b.list) # 36993344 36993344
Alexander Zhukov
  • 4,357
  • 1
  • 20
  • 31