On Sun, 26 Jun 2005 17:58:11 -0400, George Sakkis wrote (in article <[EMAIL PROTECTED]>):
> "Paul McGuire" <[EMAIL PROTECTED]> wrote: > >> Lee C - >> >> Here is a technique for avoiding the if-elseif-elseif...-else method >> for building objects. It is a modified form of ChainOfResponsibility >> pattern, in which you have a collection of factory methods that all >> have a common signature, or a collection of Factory classes that all >> implement a "makeObject" method. These common methods probably take a >> string, and return a generic object. Fortunately, such type >> flexibility is *very* easy in Python. :) >> >> Example: >> I want to convert individual strings to native data types. I want to >> detect integers, reals, complex numbers, and booleans (indicated by >> 'True' or 'False'). This is kind of similar to a parsing problem, but >> it could also be used for deserializing or unpickling data of an >> unknown original type. >> >> Note the special treatment I have to go through with boolean values - I >> needed to write a special makeBool routine, since Python will take any >> non-empty string to be True, when what I want is 'True' to yield true >> and 'False' to yield false. >> >> Hope this gives you some alternative ideas to your cascading if's. >> >> -- Paul >> >> >> def makeBool(s): >> if s in ('True','False'): >> return s == 'True' >> raise ValueError >> >> converters = [ int, float, complex, makeBool, str ] >> >> def makeObject(stringVar): >> for conv in converters: >> try: >> val = conv(stringVar) >> except Exception: >> continue >> else: >> break; >> return val >> >> def test(s): >> val = makeObject(s) >> print s, val, type(val) >> >> test('1') >> test('1.0') >> test('1+2j') >> test('1+0j') >> test('True') >> test('False') >> test('A') >> >> prints: >> 1 1 <type 'int'> >> 1.0 1.0 <type 'float'> >> 1+2j (1+2j) <type 'complex'> >> 1+0j (1+0j) <type 'complex'> >> True True <type 'bool'> >> False False <type 'bool'> >> A A <type 'str'> > > Nice technique. Something that needs to be pointed out is that the > order of the converters *is* important; int takes precedence over > float, which take precedence over complex and bool takes precedence > over string. More succinctly: > { int -> float -> complex } > { bool -> str } > In general the converters will form a strict partially ordered set, so > the list of converters should be a topological sort of the respective > DAG. > > George > > Ah yes, there is more than one way to skin a cat :~) and your samples are helping me get a better grasp of both Python and OOP in such. I find both Bengt's and Paul's variation on a theme understandable (I must be making progress :~) and interesting. I must admit that I did have to look twice at Bengt's clever little slice on 'an' though. I had already worked my way through <a href="http://fraca7.free.fr/blog/index.php?2005/02/28/2-design-patterns-part- i---chain-of-responsibility">this</a> though, so they were that much more understandable. Actually, I'm using a superclass as a factory, similar to Steve B's example (as modified by someone I can't find the name of). The difference is that my criteria does not map easily to class names so I have the verbose decision sequence in my superclass. Of course, if I want to get really fancy, I could use the COR pattern within such. I'm making more hay out of this one little pasture than I expected (i.e. increasing my understanding) thanks to all of you. I'm going to have to start writing down names (rather than rely on this ol head) so I can properly thank everyone - like those clarifying other examples. At some point I'll put up the original top-down and OO refactored versions of my little utility in the hope that I will learn even more from criticism of my efforts. The "new deal" top-down structured programming encountered in my continuing post grad work at BU in the 1960s was easier to get a solid handle on ;') Much appreciated, Lee C "Wonder rather than doubt is the root of knowledge." --Abraham Joshua Heschel -- http://mail.python.org/mailman/listinfo/python-list