Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a list to a class python [duplicate]

I have this simple class:

class revs:
    def __init__(self, rev, us, accs = []):
        self.rev = rev
        self.us = us
        self.accs = accs

And i have this piece of code to asign values to the list and is inside of a loop

rev, usu = cada_l.split("|")
acct = each_l[:2].strip()
list_acct.append(acct)

and last, i create a dict, to manage a list of revs like this:

drevs = {}
cada = revs(rev, us, list_acct)
drevs[cada.rev] = cada

And it Works correctly with rev and us, but with list_acct is ever updating all the instances:

drevs['1'].rev
'1'
drevs['2'].rev
'2'
drevs['1'].us
'user1'
drevs['2'].us
'user2'
drevs['1'].accs
'["Doc1","Doc2"]'
drevs['2'].accs
'["Doc1","Doc2"]'

And if i change list_acct.clear(), the values in all the instances is clear, I'm still fairly new to Python and this confuses me.

Thanks

like image 331
Marco Herrarte Avatar asked May 23 '13 17:05

Marco Herrarte


1 Answers

This looks like it's happening because you're passing the same list to every object. As a result, all the objects maintain references to the same list, and since list is mutable, it appears to change "all" of them at once.

To fix this, either pass in a new empty list each time you create a revs object, or else clone the list you're passing in:

cada = revs(rev, us, list_acct[:])

Note that if list_acct contains mutable objects, you could still get into the same problem again, but one level deeper!

If you're not passing lists to the revs objects when you create them at all (I can't tell, since you're not showing your full code!), then you have the same problem, but for a different reason: in Python, default arguments are all evaluated once, at the time of the function definition. Therefore, you can get this behavior:

r1 = revs(1, 1)
r2 = revs(2, 2)
r1.accs.append("Hi!")
print(r1.accs) # prints ['Hi!']
print(r2.accs) # prints ['Hi!']

Because the default argument for the revs constructor is always pointing to the same list. See this question for an explanation as to why, but to get around it, just use None as your default instead of [].

class revs:
    def __init__(self, rev, us, accs=None):
        self.rev = rev
        self.us = us
        if accs is None:
            accs = []
        self.accs = accs
like image 136
Henry Keiter Avatar answered Nov 15 '22 00:11

Henry Keiter