R
R. David Murray
Austin Schutz said:I have a fairly simple bit of code, something like:
# This should be importing the subclasses somehow, so that the factory
# can make them.
# import Parser.One
# import Parser.Two
# or.. from Parser import *?
class Parser():
def parse:
'Implemented only in subclass'
Hmm. You need to go back to the tutorial, I think
This should be
def parse(self):
raise NotImplementedError
The raise NotImplementedError is the pythonic way of indicating
unimplemented methods in a superclass. But also take a look
at ABCs (Abstract Base Classes), which provide some nice sugar
for this kind of thing.
def make_parser(which_parser):
if(which_parser = 'one'):
return One()
else:
return Two()
Skip this, I'll rewrite it later.
# import Parser?
class One(Parser):
def parse:
'one implementation'
Again, 'def parse(self):'. Might want to make the body something
like "print 'one implementation'" so you can tell if you got
the correct parser when you test it.
class Two(Parser):
def parse:
'another implementation'
Same comments as above.
The problem I have is that I don't understand how to put this into
actual files in actual directories and have the interpreter do
something actually useful. What I would like to do is something
like:
lib/
Parser.py
Parser/
Well, there's your first import mistake
and a package both with the same name, nor do you need to. So drop the
'Parser.py'. And rename the directory 'parser'; module and package
names are lower case according to the Python style guide.
__init__.py (maybe?)
Yes. Required if you are going to have a package you can import
things from.
One.py
Two.py
Again, rename these to 'one.py' and 'two.py'. Then in your
__init__.py file, do:
from one import One
from two import Two
Now, in your code that uses the parser, do:
from parser import One as Parser
or
from parser import Two as Parser
depending on which parser you want.
Unless your parsers are really heavy, you could probably just
keep all this stuff in one file, parser.py...but if they are complex
enough you want to split the source up, and you want a base class
or ABC, then put that in another file (parserbase.py, perhaps),
and at the top of each of the individual parser files do
from parserbase import ParserBase
(or some such name).
Now, if you really need the parser to instantiate to be chosen at run
time via a string, you could add something like this to your __init__.py:
def parserFactory(which_parser):
return globals()[which_parser.capitalize()]()
which will look up the capitalized version of the string (eg: 'One')
in the __init__.py module's global namespace, thus picking up the
class, and then calls it to create an instance, which is then
returned.
Then your code that uses this can do:
from parser import parserFactory
myparser = parserFactory('one')
Java or some similar language....you don't have to work as hardFrom your class heavy patterns I am guessing you are coming from
to get things done in Python.