Python class method adds stuff I'm not telling it to add

It's my first time creating a class. I'm quite confused as to why the below code acts the way it does.

from collections import Iterable
from six import string_types

class Vols:

    def __init__(self, name, recv=[], send=[]):
        self.name = name
        self.recv = recv
        self.send = send

    def assign_to(self, dest):
        if isinstance(dest, Iterable) and not isinstance(dest, string_types):
            for v in dest:
                if isinstance(v, SyncVols):
                    self.send.append(v)
                    v.recv.append(self)
        elif isinstance(dest, SyncVols):
            self.send.append(dest)
            dest.recv.append(self)
        else:
            raise TypeError("Destination must be object in class Vols or Iterable")
        return

When I set

 vol1 = Vols("vol1")
 vol2 = Vols("vol2")

and run vol2.assign_to(vol1), it adds vol2 to vol2.recv.
It adds itself to it's own recv list. Why??? Is there something I'm missing with self?
I tried adding an if/else statement to make sure dest != self, but that didn't change anything.

The problem is your default arguments. Look at this code:

a = []
b = a
b.append(1)
print(a)
print(b)

Both a and b will evaluate to [1] because they both hold the same list instance. Your code does something very similar.

Python (stupidly) only evaluates the default arguments once and then uses that result every time the value is required. So python will evaluate the [] once, and use the very same instance every time you instantiate a new Vols. The usual method to get around this behaviour is something like this:

def __init__(self, name, recv=None, send=None):
    recv = [] if recv is None else recv
    send = [] if send is None else send
4 Likes

Yes! That did it. Thank you!