Search code examples
pythoncopyvariable-assignmentassignment-operator

Is Copying for List Assignments acceptable?


Consider the following minimal example:

class MyClass():
    def __init__(self, length):
        self._list = [[] for _ in range(length)]
    def __setitem__(self, key, value):
        self._list[key] = value.copy()
    def __getitem__(self, key):
        return self._list[key]

Now, the Python documentation says:

Assignment statements in Python do not copy objects, they create bindings between a target and an object.

Applying the class above would mean something like:

>>> l = [[1,2,3,4], [3,2,1,0]]
>>> C = MyClass(2)
>>> C[0] = l[0]

This is indeed an assignment statement. But the values are copies now:

>>> C[0] == l[0]
True
>>> C[0] is l[0]
False

Is that an acceptable behavior for a class in Python?


Solution

  • There is nothing inherently wrong with this. As long as your class is well documented, if you have a good reason to do this go for it. Consider the following class from the standard library shelve module, which essentially provides a dict-like database interface. Since using object[key] = value will write to disk, and retrieving that object will retrieve it from disk, it won't give you the same object (necessarily, there are caching options)! So:

    In [1]: import shelve
    
    In [2]: data = [[1,2,3],[4,5,6]]
    
    In [3]: database = shelve.open('db')
    
    In [4]: database['key'] = data[0]
    
    In [5]: database['key']
    Out[5]: [1, 2, 3]
    
    In [6]: database['key'] is data[0]
    Out[6]: False
    

    That part of the documentation is referring to assignment statements to a variable, like this:

    some_var = foo
    

    Where indeed, it never copies. And you can't really change that (well, maybe, but that's another question). You are free to implement __setitem__ and __getitem__ however you wish.