pawamoy
pawamoy

Reputation: 3806

Concatenate class variable through inheritance?

I am trying to implicitly concatenate class variables through inheritance. I was able to go up one level but not more... It this actually possible?

class Base(object):
    def get_crumbs(self):
        crumbs = getattr(super(self.__class__, self), 'crumbs', ())
        crumbs += getattr(self, 'crumbs', ())
        return crumbs


class A(Base):
    crumbs = ('un chasseur', )


class B(A):
    crumbs = ('sachant chasser', )


class C(B):
    crumbs = ('sans son chien', 'est un bon chasseur')


>>> c = C()
>>> c.get_crumbs()
>>> <type 'tuple'>: ('sachant chasser', 'sans son chien', 'est un bon chasseur')

Upvotes: 1

Views: 335

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121834

You can loop over the class.__mro__ tuple:

class Base(object):
    def get_crumbs(self):
        crumbs = []
        for cls in type(self).__mro__:
            crumbs.extend(getattr(cls, 'crumbs', ()))
        return tuple(crumbs)

Demo:

>>> class Base(object):
...     def get_crumbs(self):
...         crumbs = []
...         for cls in type(self).__mro__:
...             crumbs.extend(getattr(cls, 'crumbs', ()))
...         return tuple(crumbs)
...
>>> class A(Base):
...     crumbs = ('un chasseur',)
...
>>> class B(A):
...     crumbs = ('sachant chasser',)
...
>>> class C(B):
...     crumbs = ('sans son chien', 'est un bon chasseur')
...
>>> c = C()
>>> c.get_crumbs()
('sans son chien', 'est un bon chasseur', 'sachant chasser', 'un chasseur')

Side note: don't use super(self.__class__, self), ever. That'll lead to infinite recursion if you ever override the get_crumbs() method and use super() to call the original, see How to avoid infinite recursion with super()?. Use super(ClassName, self) or (Python 3 only) super(), instead.

Upvotes: 3

Related Questions