1

I am dealing with issues regarding initialization of classes. Here is a reproducing example highlighting the underlying issue (I did not manage to make it much smaller):

Classes

We have two classes A,B. The hierarchy goes

  1. A: First class - instances have two attributes link;name
  2. B: This class has an A-instance as one of its attributes.

In order to faster declare instances of B I considered the following: B(name=name) which behind the curtains does B(a=A(name=name)).

Here is the code

 class A(object):
    def __init__(self, link='', name=''):
        self.name = name
        self.link = link

class B(object):
    def __init__(self, a=A(), value=0, link='', name=''):
        # Two ways to initialize "self.a":
        # 1. If "name" or "link" provided
        # 2. With "a" provided
        if {name, link}.difference({''}):
            self.a = A(name=name, link=link)
        else:
            self.a = a
        # Rest
        self.value = value

    def __str__(self):
        return 'Instance:\nname:\t{}\nlink:\t{}\nvalue:\t{}'.format(self.a.name, self.a.link, self.value)

Test

Here are two small tests:

  1. The first one defines two instances b1;b2 using __init__.
  2. The second one defines the instances as empty (B()) and then proceeds to populate/overwrite the fields.

As one can see below, the second option is problematic as it overwrites the classe's default values.

# 1. Set it all inside init
b1 = B(link=link, name=name, value=value)
b2 = B(value=value)
print(b1)
# Instance:
# name: world
# link: hello
# value:    1
print(b2) 
# Instance:
# name: 
# link: 
# value:    1

# NO PROBLEM

# 2. Define empty instances and populate
b1 = B()
b1.a.link = link
b1.a.name = name
b1.value = values[0]
b2 = B()
b2.value = values[1]
print(b1)
# Instance:
# name: world
# link: hello
# value:    1
print(b2)
# Instance:
# name: world
# link: hello
# value:    2

# PROBLEM

How can I guarantee for this problem not to occurr? Should I overwrite the __new__ method, add getters/setter, work with copies (copy.deepcopy), etc. ?

user101
  • 476
  • 1
  • 4
  • 9
  • 1
    Never use mutables as default values. Use `None`, then `self.a = a if a else A()` (if `a` value exists, set it, otherwise use `A()`). Most IDEs (e.g. PyCharm) underline mutables in defaults to warn you about not recommended usage. – h4z3 Jun 19 '19 at 09:10
  • @h4z3 Thanks that helped! Atom did not seem to care much about mutables – user101 Jun 19 '19 at 09:16

0 Answers0