setattr question

bruno at modulix onurb at xiludom.gro
Fri Mar 3 14:59:18 CET 2006

Gerard Flanagan wrote:
> bruno at modulix wrote:
> [...]
>>I don't know this HtmlElement class, nor where it comes from.
>>'to_string()' (or is it toString() ?) is javaish. The pythonic idiom for
>>this is implementing the __str__() method and calling str(obj) on the
>>obj (which will call obj.__str__()). Hence my (bad) guess about you
>>being a Javaer.
> I've made this change, thanks. ( I had a year with C# so maybe that's
> why I'm so idiomatically-challenged ! )

Well, C# being somewhat inspired by Java...

>>Not the HtmlElement class, but the HtmlBuilder one. Here again, a class
>>defining only staticmethods is a pretty javaish idiom - in Python, we
>>just use good old functions !-) (in a separate module if you want a
>>separate namespace).
> But it's personal preference, no? 

Well, in Python, there are a lot of things that can be done the way you
like it, but are better done the idiomatic way. Python relies quite a
lot on conventions and idioms where other languages try to inforce
strict rules.

> The functions were kind of related
> and meaningless outside the module they were declared - 

FWIW (and from the snippet I saw), these functions are useless even in
the module !-)

Unless you want to dynamically choose the concrete class at runtime
based on platform/settings/phase of the moon/whatnot (which seems not to
be te case in the snippet you posted), you don't need these functions,
just instanciating the concrete class is enough. Remember that Python
classes *are* factory already - and that you can freely replace a class
by any callable returning an instance, ie:

== before refactoring, directly instanciating concrete class ==
class HtmlElement(tag, *args, **kw):
  # code here

from myhtmlmodule import HtmlElement
ul = HtmlElement('ul')

== after refactoring, using a factory function ==
class _HtmlElement1(tag, *args, **kw):
  # code here

class _HtmlElement2(tag, *args, **kw):
  # other code here

# yes, it's now a function...
def HtmlElement(tag, *args, **kw):
  if phase_of_the_moon():
    klass = _HtmlElement1
    klass = _HtmlElement2
  return klass(tag, *args, **kw)

# well... nothing changed here !-)
from myhtmlmodule import HtmlElement
ul = HtmlElement('ul')

You could also do the trick with metaclass black magic, but what, KISS...

> but I'll take
> it on board, anyway.
> [...]
>>My experience is that it's far easier to start simple and add
>>flexibility where needed than to simplify useless complexity. KISS,
>>yagni and all that kind of things...
> yagni - I'd never heard that one!

You Aint Gonna Need It.

Code not written is the best code, so don't write code "just in case".
Python is usually dynamic enough to make refactoring easy (cf example above)

> I've ditched the factory class in any case:
> (FWIW)

Seems mostly clean. May I suggest a couple small corrections/improvements ?

1/ potential bugfix:
    from tidy import parseString
except ImportError:
    def parseString(text):
        # woops, this function is supposed to return something
        return text

2/ safer and cleaner
class HtmlPage(HtmlElement):
    # removed class vars,
    # replaced with default in __init__
    def __init__(self, title, **kw):
        self.title = title
    	self.stylesheets = kw.get('stylesheets', [])
        self.doctype = kw.get('doctype', HTML4_STRICT)

>>BTW, there's also a french speaking python newsgroup at
> I wasn't aware of that, I'll have a lurk!

see you there !-)

>>bruno desthuilliers
>>python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
>>p in 'onurb at xiludom.gro'.split('@')])"

bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"

More information about the Python-list mailing list