# Inheritance and forcing methods to be called inside another method [closed]

I've written a text parser that extracts useful information from a given text. Texts are formatted different, so there are different specialized parsers. I've designed them so that they all must define the methods from the interface Parser.

class Parser:
def parse(text):
raise NotImplementedError

def pre_validate(text):
raise NotImplementedError

def post_validate():
raise NotImplementedError


How can I force all subclasses of Parser to call pre_validate before running parse and post_validate after calling parse?

I could solve it like this, but I don't think it's very elegant to wrap methods like this:

class Parser:
def parse(text):
self.pre_validate(text)
self._parse()
self.post_validate(text)

def _parse(text):
raise NotImplementedError

def pre_validate(text):
raise NotImplementedError

def post_validate():
raise NotImplementedError


Ideally I'd like to allow the subclasses to implement the method parse instead of _parse. What's the recommended way of solving this? Would it make sense to use a python decorator here?

You could fix the issue by making parser a collection of callables, rather than a class with fixed methods. This would be handy for other aspects of this kind of parsing, so you could easily reuse pre-parsing and post-parsing functions that might be more similar than the parsing:

class ParseOperation(object):

def __init__(self, pre_validator, parser, post_validator):
self.pre_validator = pre_validator
self.parser= parser
self.post_validator= post_validator

def parse(self, text):
self.pre_validator(self, text)
self.parser(self, text)
self.post_validator(self, text)

class Validator(object):

def validate(self, owner, text):
print 'validating %s' % text

def __call__(self, owner, text):
self.validate(owner, text)

class Parser (object):
def parse(self, owner, text):
print 'parsing %s' % text

def __call__(self, owner, text):
self.parse(owner, text)


Instead of overriding methods, you subclass Parser and Validator to compose your parse operation.

You could achieve that like this:

class Parser:
def __init__(self):
self.parse = self._validated_parsing(self.parse)

def parse(self, text):
raise NotImplementedError

def pre_validate(self, text):
raise NotImplementedError

def post_validate(self, text):
raise NotImplementedError

def _validated_parsing(self, parse_func):
def parse_wrapper(text):
self.pre_validate(text)
parse_func(text)
self.post_validate(text)
return parse_wrapper

class ParserChild(Parser):
def parse(self, text):
print('parsing')

def pre_validate(self, text):
print('pre-validating')

def post_validate(self, text):
print('post-validating')

ParserChild().parse('spam')
# pre-validating
# parsing
# post-validating


I recommend doing it with an extra method that is called from parse though, like the _parse method you wrote. It should not be called directly from outside, so it should be written with a leading underscore. You might want to want to call it something more explicit, such as (in lack of a better name) _core_parse.

While we're at it, maybe pre_validate and post_validate should be preceded with an underscore too (depending on whether you want them to be called from outside the class).

Instead of raising NotImplementedError in the base class, you should use abc.ABCMeta for an abstract base class. This is better for two reasons:

• You can't create a subclass that doesn't implement all abstract methods.
• It will work together properly with the super function which delegates calls to superclasses (base classes).

So, I think I would implement the class like this:

import abc

class Parser(object):
__metaclass__ = abc.ABCMeta

def parse(self, text):
self._pre_validate(text)
self._core_parse(text)
self._post_validate(text)

@abc.abstractmethod
def _pre_validate(self, text):
pass

@abc.abstractmethod
def _core_parse(self, text):
pass

@abc.abstractmethod
def _post_validate(self, text):
pass

class ParserChild(Parser):
def _core_parse(self, text):
print('parsing')

def _pre_validate(self, text):
print('pre-validating')

def _post_validate(self, text):
print('post-validating')

ParserChild().parse('spamspam')
# pre-validating
# parsing
# post-validating


(I'm assuming you use Python 3, but if you're using Python 2, you should let Parser inherit from object. In Python 3, this happens automatically.)