Python Forum

Full Version: Extending list doesn't work as expected
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Adding a list using the += operator or the extend function gives strange results when used in a class (maybe also outslde a class, I didn't check this).
This is an example script to demonstate this:

class Test:
    def __init__(self):
        self.list1 = [1, 2, 3]
        self.list2 = [5, 6, 7]

    def f(self, opt=1):
        h = self.list1
        if opt == 2:
            h = self.list2
        if opt == 3:
            h = self.list1 + self.list2
        if opt == 4:
            h.extend(self.list2)
        return h

t = Test()
print('Print the first list:', t.f(1))
print('Print the second list:', t.f(2))
print('Two lists added together:', t.f(3))
print('First list again:', t.f(1))
print('Exntending one list with the other:', t.f(4))
print('Should only print the first list:', t.f(1))
print('Printing the second list -- works:', t.f(2))
Every call of f(), h is initialised with list1. Somehow this doesn't seem to work if during a previous call of f() h was extended to.
If another list is added to h by explicitly adding two lists together it does work.
It is also strange that everything works well if I later on select the second list only.
I don't understand what is happening here.
list1, lst2 are attributes. h is a variable. These are all references to objects, not objects themselves. When you execute "h = list1", you are assigning the variable "h" to reference the object reverenced by "self.list1". Now "h" and "self.list1" reference the same list object. When you execute "h.extend(self.list2)", you modify the object referenced by h, which is also referenced by "self.list1". self.list1 is unchanged, only the list object referenced by self.list1 has changed.

An object and a variable that references an object are two very different things in Python. Understanding this is key to understanding Python.
I think, outside of the class Test you would need a copy of list1 or list2, or you will alter them, but within the class, this seems to work ok without list1.copy() or list2.copy().

Oh the joys of classes!

class Test:
    def __init__(self):
        self.list1 = [1, 2, 3]
        self.list2 = [5, 6, 7]
 
    def f(self, opt=1):
        if not opt in (1, 2, 3, 4):
            raise ValueError('f() only takes 1, 2 ,3 or 4 as options.')
        if opt == 1:
            h = self.list1
        elif opt == 2:
            h = self.list2
        elif opt == 3:
            h = self.list1 + self.list2
        elif opt == 4:
            h = self.list1 + self.list2
            h.extend(self.list2)
        return h

t = Test()
t.f()
t.f(2)
t.f(3)
t.f(4)
t.f(5)
Of course, you can reassign t.list1 or t.list2 to another list!