[Guido van Rossum] > > I am more worried about the inefficiency of instantiating > self.__class__ and then throwing it away after calling str() on it. > You could factor out the body of __str__ into a separate method so > that you can invoke it from __call__ without creating an instance. Some more code from the module might help explain this design decision. I'm still sort of toying with this to see if I like it. The basic idea here is that I'm trying to support both DOM-like xhtml structures as well as simple function-like callables that return strings. When the instance is called it needs a fresh state in order to better mimic a true function. It isn't immediately obvious to me how I might refactor this to avoid instantiating a throwaway. class Element: def __init__(self, klass, id, style, title): self.name = self.__class__.__name__.lower() self.attrs = { 'class': klass, # Space-separated list of classes. 'id': id, # Document-wide unique id. 'style': style, # Associated style info. 'title': title, # Advisory title/amplification. } def attrstring(self): attrs = self.attrs.keys() attrs.sort() # Sorting is only cosmetic, not required. l = [] # List of formatted attribute/value pairs. for attr in attrs: value = self.attrs[attr] if value is not None and value != '': l += ['%s="%s"' % (attr, convert(value))] s = ' ' + ' '.join(l) # Prepend a single space. return s.rstrip() # Reduce to an empty string if no attrs. def __str__(self): pass def __repr__(self): return repr(self.__str__()) class EmptyElement(Element): def __init__(self, klass=None, id=None, style=None, title=None): Element.__init__(self, klass, id, style, title) def __call__(self, klass=None, id=None, style=None, title=None): o = self.__class__(klass, id, style, title) return str(o) def __str__(self): attrstring = self.attrstring() return '<%s%s />\n' % (self.name, attrstring) class SimpleElement(Element): def __init__(self, content='', klass=None, id=None, style=None, title=None): self.content = content Element.__init__(self, klass, id, style, title) def __call__(self, content='', klass=None, id=None, style=None, title=None): o = self.__class__(content, klass, id, style, title) return str(o) def __str__(self): attrstring = self.attrstring() return '<%s%s>\n%s\n</%s>\n' % \ (self.name, attrstring, convert(self.content), self.name) class Br(EmptyElement): pass class Hr(EmptyElement): pass class P(SimpleElement): pass # The following singleton instances are callable, returning strings. # They can be used like simple functions to return properly tagged contents. br = Br() comment = Comment() hr = Hr() p = P() > BTW I have another gripe about your example. > > > def __str__(self): > > return '<!-- %s -->' % self.content > > > > def __repr__(self): > > return repr(self.__str__()) > > This definition of __repr__ makes no sense to me -- all it does is add > string quotes around the contents of the string (and escape > non-printing characters and quotes if there are any). That is > confusing, because it will appear to the reader as if the object is a > string. Yes. This was a conscious design choice for this particular application. Maybe there is a better way, and maybe I'm not being too Pythonic, but I'm not particularly troubled by this even though I know I'm "breaking the rules". I guess I don't mind if there is more than one way to do something, as long as one way is the Python way and the other way is my way. ;-) --- Patrick K. O'Brien Orbtech
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4