1

I am having a problem with default arguments in python classes. It seems that when an argument is not given, the default links to the same object for all instances of a class. Example:

class My_class:
    def __init__(self,options=[]):
        self.options = options

class1 = My_class()
class2 = My_class()

class2.options.append('something')
print(class1.options)

This would print:

['something']

How can i make sure each instance of a class will have a unique list for options, instead of a reference to the same object. For example, this is how i could do it:

    def __init__(self,options=None):
        if options is None:
            options = []
        self.options = options

However, this doesnt feel correct to me. So my questions are if there is a better way to do it, and for someone to explain the initial behaviour to me since i have a clue what is going on, but i don't fully understand why

user3053216
  • 777
  • 1
  • 9
  • 24
  • 1
    That's a classic, and very controversial, Python gotcha. Almost certainly a duplicate. – jkm Nov 20 '17 at 13:23
  • @jkm I am very sure that this was already asked before. However, i don't think that makes my question not valid since in the way i phrased it i could not find it, and probably other people will have the same problem. It is also the reason why i ask for some explanation and not just a solution, because i lack the knowledge and terminology to find this myself. – user3053216 Nov 20 '17 at 13:24
  • 1
    @user3053216 cf https://stackoverflow.com/questions/1132941 - and your solution is the canonical one. – bruno desthuilliers Nov 20 '17 at 13:30
  • @brunodesthuilliers Great, the article linked to the top comment explained very clear what happens. Thank you! – user3053216 Nov 20 '17 at 13:48

2 Answers2

2

This is one of most common python gotchas.

Python’s default arguments are evaluated once when the function is defined, not each time the function is called. This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well. Your second variant with None is just fine and is widely used in python.

user2021091
  • 561
  • 2
  • 11
Dmitry Kovriga
  • 238
  • 3
  • 8
-1

Both object using same reference to the list I guess, When you assign it is like shallow copy , Try this deepcopy which will create new list for both objects.

import copy
class My_class:
    def __init__(self,options=[]):
        self.options = copy.deepcopy(options)

class1 = My_class()
class2 = My_class()

class2.options.append('something')
print(class1.options)
print(class2.options)