Ruud de Jong wrote: > Steven Bethard schreef: >> But unless the person eval-ing your code *only* writes immaculate >> code I can see that you can probably screw them. ;) I wonder why >> __subclasses__ isn't a restricted attribute... Is it ever used for >> something that isn't evil? ;) >> >> STeVe > > Completely off topic, but I just cannot resist showing off. > Some time ago I used __subclasses__ in a way that is not evil. I > think. > > The details are described in the following thread: > http://groups.google.nl/group/comp.lang.python/browse_thread/thread/5c1 > ccb986c66cdc1/ > > A summary: I used __subclasses__ to apply the Chain-of-Responsibility > pattern to object creation. The code would appear to instantiate > an object of the root of a class hierarchy, but the actual object > that was created would be an instance of a subclass. > > So to get back to your question: yes, there are non-evil > uses for __subclasses__. Weird perhaps, but non-evil. > Non-standard, sure . Too clever for my own good, very likely.
I've done almost exactly the same thing. The base class uses __subclasses__ to find the best matching subclass based on the factory parameters. In my case I was retrieving files from the web, so I had a base Handler class and created HtmlHandler, ImageHandler &c. class Handler(object): '''Class to process files''' __map = {} @classmethod def _resolveClass(klass, isdir, name): map = Handler.__map if not map: for c in klass.__subclasses__(): for ext in c.Extensions: map['.'+ext.lower()] = c if isdir: klass = FolderHandler else: ext = os.path.splitext(name)[1].lower() if ext not in map: map[ext] = DefaultHandler klass = map[ext] return klass(name) @classmethod def fromPathname(klass, name, path, uri, db): isdir = os.path.isdir(os.path.join(path, name)) obj = klass._resolveClass(isdir, name) obj._initialize(name, path, uri, db) return obj @classmethod def fromUrl(klass, uri, text, db=None): ... and so on ... and then subclasses such as: class ImageHandler(Handler): Extensions = ('jpg', 'jpeg', 'gif', 'png') type = 'Image' class DefaultHandler(Handler): Extensions = ('',) type = 'Ignored' This also contains the only code I think I've written with a class definition in a for loop: # General categories EXTENSIONS = { 'js': 'javascript', 'php': 'php', 'doc': 'Word Document', 'xls': 'Spreadsheet', 'ppt': 'Powerpoint', 'css': 'Stylesheet', 'swf': 'Flash', 'pdf': 'File', 'rtf': 'File', 'zip': 'File', } Classes = [] for ext in EXTENSIONS: class GeneralHandler(Handler): Extensions = (ext,) type = EXTENSIONS[ext] Classes.append(GeneralHandler) -- http://mail.python.org/mailman/listinfo/python-list