Dux
Dux

Reputation: 1246

Add to parentclass's class attribute in subclass

I may be on the wrong path here, so if my approach to this is bogus, please advice.

Basically I have a class that has a dictionary containing printing information for every property. I create a child of this class that adds another property:

class A(object):

    _print_dict = {"a": "ms"}

    def __init__(self):
        self.a = 5

    def __str__(self):
        s = ""
        for attr in self._print_dict:
            s += "{} {}\n".format(getattr(self, attr), _print_dict[attr])
        return s

class B(A):

    def __init__(self):
        super(B, self).__init__()
        self.b = 10

I could update in B.__init__, but that would make _print_dicta instance attribute, right?

class B(A):

    def __init__(self):
        super(B, self).__init__()
        self.b = 10
        self._print_dict.update({"b": "V"})

When trying to access _print_dict outside __init__ however, i get a NameError:

class B(A):

    _print_dict.update({"b": "V"})

    def __init__(self):
        super(B, self).__init__()
        self.b = 10

The same obviously happens with self._print_dict, since self is not defined when the class is created (I presume).

Is there a way to alter the class attribute _print_dict in the subclass B? Without altering it for class A as well?

Edit:

I obviously missed using the parent class's name explicitly:

class B(A):

    _print_dict = A._print_dict.copy()
    _print_dict.update({"b": "V"})

    def __init__(self):
        super(B, self).__init__()
        self.b = 10

Is this the way to do it? At least it seems to work...

Upvotes: 0

Views: 1881

Answers (1)

mkrieger1
mkrieger1

Reputation: 23144

Updating the dictionary in B.__init__ would not make it an instance attribute. Instead, you would modify the same dictionary each time you make an instance of B:

>>> class A(object):
...     _print_dict = {"a": "ms"}
...
>>> class B(A):
...     def __init__(self):
...         self._print_dict.update({"b": "V"})
...
>>> A._print_dict is B._print_dict
True # they are the same object
>>> A._print_dict
{'a': 'ms'} # not yet updated
>>> b = B()
>>> A._print_dict is B._print_dict is b._print_dict
True # still the same object
>>> A._print_dict
{'a': 'ms', 'b': 'V'}

If you want to preserve the original dictionary in A, you have to copy it in the class definition of B. Dictionaries convieniently have a method for this:

>>> class B(A):
...     _print_dict = A._print_dict.copy()
...     _print_dict.update({'b': 'V'})
...
>>> A._print_dict is B._print_dict
False # now they are two distinct objects
>>> A._print_dict
{'a': 'ms'}
>>> B._print_dict
{'a': 'ms', 'b': 'V'}

Upvotes: 1

Related Questions