1

I'm using class attributes as a neat way to keep common strings used throughout my project. Parent class has an 'main' attribute that is used to compose other attributes.

Some of use cases need to use child class with this 'main' attribute changed. How can I force the child class to run the parent class attributes initialization for not-overridden attributes?

Basically, I want this code to work:

class One:
    MAIN_ATTR = 'one'
    COMPOSED_ATTR = ' '.join([MAIN_ATTR, 'composed'])


class Two(One):
    MAIN_ATTR = 'two'

assert Two.COMPOSED_ATTR == 'two composed'
Mirek
  • 355
  • 4
  • 16
  • Is there any reason why don't use constructor and change attribute inside the constructor? – Bulva Feb 20 '19 at 10:16
  • @Bulva Such constructor would be required within each child class. I want to define the child class as simply as possible, best by just adding proper metaclass to it. – Mirek Feb 20 '19 at 10:25

1 Answers1

1

You can use metaclass to construct attributes of both parent and child classes:

#!/usr/bin/python3.6


class Composer(type):
    def __new__(cls, name, bases, attrs):
        attrs['COMPOSED_ATTR'] = ' '.join([attrs['MAIN_ATTR'], 'composed'])
        return super(Composer, cls).__new__(cls, name, bases, attrs)


class One(metaclass=Composer):
    MAIN_ATTR = 'one'


class Two(One):
    MAIN_ATTR = 'two'


assert Two.COMPOSED_ATTR == 'two composed'
sanyassh
  • 8,100
  • 13
  • 36
  • 70
  • Thanks! Unfortunately, that would require to define the parent class behavior in its metaclass, i.e. I'd need metaclass for every such parent class. Not really convenient, the parent attributes should be defined within parent. – Mirek Feb 20 '19 at 10:35
  • Why do you need metaclass for every parent class? I think you could have only one metaclass that will do all the work for every parent class – sanyassh Feb 20 '19 at 10:47
  • your example is setting `COMPOSED_ATTR` in the metaclass, not in parent, so if we have another parent class, we'd need another metaclass for it. – Mirek Feb 20 '19 at 10:48
  • What about setting `COMPOSED_ATTR_2` in the same metaclass? Also you can use some `if` conditions inside the `__new__` method to determine what attrs you want to set – sanyassh Feb 20 '19 at 10:51
  • it wouldn't be really convenient. I'd prefer a solution in which the parent and class are defined as close as the ones in my question. I need this for DRY approach on command string building for a test framework. There is lots of commands, frequently changing, so to avoid mistakes it should be as simple as possible to define a new string. If this cannot be done via class attributes, I'd have to use another solution, like dictionaries. But with class attributes, I'd benefit from IDE auto-completion. – Mirek Feb 20 '19 at 10:55