On Thu, Mar 19, 2009 at 6:52 PM, Austin Schutz <t...@off.org> wrote: > > 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' > > def make_parser(which_parser): > if(which_parser = 'one'): > return One() > else: > return Two() > > # import Parser? > class One(Parser): > def parse: > 'one implementation' > > class Two(Parser): > def parse: > 'another implementation' > > 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/ > __init__.py (maybe?) > One.py > Two.py > > But I'm not clear on how to structure the import statements. I'm a bit > of a newb wrt python, and I get any number of different errors depending > on how I arrange the import statements, everything from > > AttributeError: 'module' object has no attribute 'make_parser' > to > ImportError: cannot import name > to > TypeError: Error when calling the metaclass bases > > depending on how I use import. Nothing seems to be the correct > combination. Any help would be much appreciated! > > Austin > > This seems to be a good use for a metaclass, though it's tricky to work around the fact that the new class doesn't exist when the metaclass is called.To get around this, I have the metaclass add the new Parser to a "to-do" list. The metaclass will be called whenever a subclass is created, so every class that subclasses parser will automatically be added.
BTW, don't create a class and a package with the same name. When you import Parser, python won't know whether you want Parser.py or Parser/__init__.py. I'm not very good with metaclasses, so there might be a couple mistakes in here. Note that this won't work if you run this as the main script because then you end up with two copies of Parser (Parser.Parser and __main__.Parser). class ParserMeta(type) : #the metaclass is called when the class is created def __new__(cls, *args) : #args = (name, bases, dict). dict has __module__ in it. #we don't want to add the base class if args[0] != "Parser" : Parser._not_loaded_parsers.append(args) return type.__new__(cls, *args) #note that this is for Python 3. #for python 2.x do: #class Parser(object) : # __metaclass__ = ParserMeta class Parser(metaclass=ParserMeta) : _not_loaded_parsers = [] #the parsers that aren't loaded yet parsers = {} #the list of parsers- names mapped to the class. def parse(self) : raise NotImplementedError @classmethod def load(cls) : """ This method will add the parsers to the dictionary if they aren't already in there""" while cls._not_loaded_parsers : new_parser = cls._not_loaded_parsers.pop() mod = __import__(new_parser[2]['__module__'], fromlist=['*']) cls.parsers[new_parser[0]] = mod.__dict__[new_parser[0]] @classmethod def make_parser(cls, which_one) : """loads the parsers if necessary and returns the parsers""" cls.load() return cls.parsers[which_one]() import modules-that-contain-other-parsers Parser.load() > > > > > -- > http://mail.python.org/mailman/listinfo/python-list >
-- http://mail.python.org/mailman/listinfo/python-list