U
U
uniquepeero2022-04-20 09:52:01
Python
uniquepeero, 2022-04-20 09:52:01

How to use class attributes in another class without inheritance?

There are several base classes:

# base.py

class BaseParser:
   _SOURCE = NotImplemented

   def parse():
      print(f'base from {self.source}')
    
class FooBaseParser:
   _SOURCE = NotImplemented

   def parse():
      print(f'foo from {self.source}')


There are also several worker classes, usually looking like this:
# module parser_a.py
class AParser(BaseParser):
   _SOURCE = 'aaa.aaa'

# module parser_b.py
class BParser(BaseParser):
   _SOURCE = 'bbb.bbb'

# module parser_c.py
class CParser(FooBaseParser):
   _SOURCE = 'ccc.ccc'


and modules that work with parsers, for example:
# work_a.py

class AWork:
    _PARSER = AParser

    def work():
       parser = self._PARSER()
       parser.parse()


Now you need to implement the choice of the base parser for each of the workers depending on the condition, so far I see it like this (working with modules is strict):

Maybe you can use some design pattern, but I didn’t figure out which
# base.py

class ParserSelector:
    def __init__(self, foo, *args, **kwargs):
        self.init = foo, args, kwargs

    def get_parser(foo):
       return FooBaseParser if foo else BaseParser

    def parse():
       foo, args, kwargs = self.init
       parser = self.get_parser(foo)
       return parser(*args, **kwargs).parse()


Working parsers:
# parser_a.py
class AParser(ParserSelector):
   _SOURCE = 'aaa.aaa'

# parser_c.py
class CParser(ParserSelector):
   _SOURCE = 'ccc.ccc'

# work_a.py

class AWork:
    _PARSER = AParser

    def work():
       parser = self._PARSER(foo=False)
       parser.parse() #prints 'bar from aaa.aaa'

# work_c.py

class CWork:
    _PARSER = CParser

    def work():
       parser = self._PARSER(foo=True)
       parser.parse()  #prints 'foo from ccc.ccc'

in this case, the problem remains that the overridden attribute of the SOURCE class is not forwarded to the base classes. The place to find it is in ParserSelector's self. Since it is possible to forward class attributes to the base one without resorting to redefining each instance attribute somewhere in the init'e of the base one, since there are quite a lot of them

To avoid this:
class BaseParser:
   _SOURCE = NotImplemented

   def __init__(self, child_self):
      self._SOURCE = child_self._SOURCE

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question