Re: Switch function
On 2/3/19 9:03 PM, Avi Gross wrote: > The example I show above could in many cases be done as you describe > but what are you gaining? > > I mean if I subtract the integer representation of a keyboard > alphabetic letter (ASCII for the example) from letter 'a' or 'A' then > A maps to 0 and B maps to 1 and ... Z maps to 26. So, you could make > a list of 26 functions (some may be absent) and your entire switch > statement looks like: > >funcs=[zeroeth,first,other,...,last] # list of function handles >var=input("Enter a Command: ") >if ord('A') <= ord(var[0]) <= ord('Z'): >result = funcs[ord(var[0]) - ord('A')]() > > Is that short enough? It's not a matter of shortness. Your code encapsulates the idea of dispatching to a 0-airity function based on an input. In Python, though, I'd still use a dictionary, which would be more flexible (what if I start to use digits or other characters as commands?) and less error prone. > Your comment about object polymorphism is interesting. I am picturing > how each choice somehow delivers an object that automatically is set > up to do the right thing. Disclaimer: I speak OO as a second language, and only when there is an obvious and compelling advantage over some other paradigm. That said: If the mapping from input to function is more complex than A -> func1, B -> func2, etc., then a factory function that builds an object with an execute method is a good way of isolating the mapping and keeping the main code clean and clear. > Again, see how can you write a COMPLICATED try command that captures > many things including real errors? Don't do that. Why are you writing COMPLICATED try commands? Did you have a Python question? ;-) -- https://mail.python.org/mailman/listinfo/python-list
RE: Switch function
Dan, I agree and have felt no need to do a method like this. Most of the time a switch is easy to avoid or even forget that it exists. I rarely needed to use these years ago when they were available in C and C++ , JAVA, JavaScript, PERL or R or under other *names* but similar functionality like COND in versions of LISP or CASE in PASCAL. The times I would use it would not be when were a relatively few cases. It makes more sense for example when you are accepting a one-character command in the very old style from the user. I repeat, OLD style. Your main loop may largely consist of a switch statement where every possible keystroke calls one of a set of functions. I mean things like D is for Delete and I is for insert and A is for Append and Q is for QUIT and some are absolutely not mnemonic like V is for Paste. I have read books that suggest having a long function is a sign of clutter or even insanity and I feel that is not realistic in many cases. The example I show above could in many cases be done as you describe but what are you gaining? I mean if I subtract the integer representation of a keyboard alphabetic letter (ASCII for the example) from letter 'a' or 'A' then A maps to 0 and B maps to 1 and ... Z maps to 26. So, you could make a list of 26 functions (some may be absent) and your entire switch statement looks like: funcs=[zeroeth,first,other,...,last] # list of function handles var=input("Enter a Command: ") if ord('A') <= ord(var[0]) <= ord('Z'): result = funcs[ord(var[0]) - ord('A')]() Is that short enough? Mind you, that is not the same as a switch statement form that allows arbitrary code after each choice and lets you access variables at that level and change them, as well as call functions with specific arguments that make sense at that time. Yes, judicious use of the global or nonlocal statement can dangerously get you some of that functionality. A reasonable goal might be to have the code at each case be relatively brief. Maybe a few lines adjusting local variables then calling a function that lets more code be elsewhere by passing in additional things needed in that context or passing in mutable arguments. The indentation should make it reasonable to follow as if you are looking at N different functions where each one is not too large even if it is all in one large switch. Now this sounds quite a bit like the dictionary trick but note many of the above languages do not have a built-in dictionary concept and some may not support lists of functions or objects. I have seen monstrosities like this: functionTop is: If var == 'A': # do something else: functionB(var) Guess what functionB says? Yep, if it is 'B" do something else call functionC. So a mere 26 functions, each short and stacked. Ugh! It may be a matter of taste and I have seen places such as statistical calculations where such an approach is even needed. In very brief, some tests require a choice of TWO so one choice is A versus non-A and then you do something with the non-A that are B versus non-B. Your comment about object polymorphism is interesting. I am picturing how each choice somehow delivers an object that automatically is set up to do the right thing. Having said that, I realize how there is something in python quite similar to a case statement! Picture my example where you have a try statement that raises at least 26 error objects followed by up to 26 catch statements: try: something that raises a designer exception catch errorA as var: pass catch errorb, errorB: pass ... catch errorZ: pass That looks like a switch in many ways and lets you combine multiple choices into one case. Heck, there is also a finally and else clause you can use for fine tuning as in setting a default. Again, see how can you write a COMPLICATED try command that captures many things including real errors? I know I keep repeating this but experience tells me that if not mentioned, someone will make believe I meant something other than what I say. The above is NOT a suggestion of what to do. It is an example of another feature that IS in the language that in some ways is much like the switch statement. Not always a good idea to abuse it when it can be done with IF variants or a dict jump or many other gimmicks. In the above the *raise* statement within whatever you try can do the same trick as before and create a small integer offset from letter 'A' to use in making a slightly different object for each case in one of many ways. I will stop here. -Original Message- From: Python-list On Behalf Of Dan Sommers Sent: Sunday, February 3, 2019 8:29 PM To: python-list@python.org Subject: Re: Switch function On 2/3/19 5:40 PM, Avi Gross wrote: > Bottom line, does anyone bother using anything like this? It is > actually a bunch of hidden IF statemen
Re: Switch function
On 2/3/19 5:40 PM, Avi Gross wrote: Bottom line, does anyone bother using anything like this? It is actually a bunch of hidden IF statements matched in order but may meet many needs. I sure don't. In the rare case that I might use a switch statement in another language, I just use a series of elifs, or maybe a dictionary I build once and use over and over (a habit left over from the old days of extremely constrained systems, when medium-to-large lookup tables and simple logic was better than many kinds of runtime computation). If it gets unweidly, I think harder about how to isolate the "switching" from the results, and usually end up with a collection of smaller functions to do the work, or high order functions, or maybe some sort of object oriented polymorphism as a last resort. -- https://mail.python.org/mailman/listinfo/python-list
Re: Switch statement
On Sun, 10 Mar 2013 14:16:27 +, Joseph L. Casale wrote: I have a switch statement composed using a dict: switch = { 'a': func_a, 'b': func_b, 'c': func_c } switch.get(var, default)() As a result of multiple functions per choice, it migrated to: switch = { 'a': (func_a1, func_a2), 'b': (func_b1, func_b2), 'c': (func_c, ) } for f in switch.get(var, (default, )): f() As a result of only some of the functions now requiring unique arguments, I presume this needs to be migrated to a if/else statement? Is there a way to maintain the switch style with the ability in this scenario to cleanly pass args only to some functions? The dict-as-switch-statement pattern only works when the functions all take the same argument(s). Otherwise, you need to check which function you are calling, and provide the right arguments. So either use the if...elif...else pattern, or you need to modify those functions to take the same arguments. For example, suppose I have three functions taking different arguments: spam(a) ham(b) eggs(c) Instead of storing spam, ham and eggs in my switch-dict, I store three wrapper functions: switch = { 'A': lambda a, b, c: spam(a), 'B': lambda a, b, c: ham(b), 'C': lambda a, b, c: eggs(c), } and then unconditionally call the function with all three arguments: switch[letter](a, b, c) The wrappers take care of ignoring the arguments that should be ignored, and calling the correct function with the right argument. Here's another similar case. Suppose the functions are called like this: spam(a, b) ham(b, c) eggs(b) and furthermore, the arguments a and c are known ahead of time, with only b varying. I can make one-argument versions of the spam and ham functions using either the functools module or a lambda with a default value: switch = { 'A': functools.partial(spam, a), 'B': lambda b, c=c: ham(b, c), 'C': eggs, } switch[letter](b) I stress that this version only applies if the extra arguments are known ahead of time. If they aren't known until you look-up the switch, you can't use this tactic. functools.partial isn't always applicable, but when it is, you should prefer it over lambda since it will be very slightly more efficient. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
RE: Switch statement
switch = { 'A': functools.partial(spam, a), 'B': lambda b, c=c: ham(b, c), 'C': eggs, } switch[letter](b) That's cool, never even thought to use lambdas. functools.partial isn't always applicable, but when it is, you should prefer it over lambda since it will be very slightly more efficient. Ok, haven't used this before but I will give it a read! Much appreciated Steven! jlc -- http://mail.python.org/mailman/listinfo/python-list
Re: Switch statement
On 03/10/2013 10:16 AM, Joseph L. Casale wrote: I have a switch statement composed using a dict: switch = { 'a': func_a, 'b': func_b, 'c': func_c } switch.get(var, default)() As a result of multiple functions per choice, it migrated to: switch = { 'a': (func_a1, func_a2), 'b': (func_b1, func_b2), 'c': (func_c, ) } for f in switch.get(var, (default, )): f() As a result of only some of the functions now requiring unique arguments, I presume this needs to be migrated to a if/else statement? Is there a way to maintain the switch style with the ability in this scenario to cleanly pass args only to some functions? Thanks, jlc You can have two dictionaries; you can also add a flag: 'a': (WITHARG, funca1, funca2) -m -- Lark's Tongue Guide to Python: http://lightbird.net/larks/ The cure for boredom is curiosity. There is no cure for curiosity. Dorothy Parker -- http://mail.python.org/mailman/listinfo/python-list
Re: Switch statement
On Sun, Mar 10, 2013 at 8:42 PM, Mitya Sirenef msire...@lightbird.netwrote: On 03/10/2013 10:16 AM, Joseph L. Casale wrote: I have a switch statement composed using a dict: switch = { 'a': func_a, 'b': func_b, 'c': func_c } switch.get(var, default)() As a result of multiple functions per choice, it migrated to: switch = { 'a': (func_a1, func_a2), 'b': (func_b1, func_b2), 'c': (func_c, ) } for f in switch.get(var, (default, )): f() As a result of only some of the functions now requiring unique arguments, I presume this needs to be migrated to a if/else statement? Is there a way to maintain the switch style with the ability in this scenario to cleanly pass args only to some functions? Or could you do something like: arguments_to_pass = [list of some sort] switch.get(var, default)(*arguments_to_pass) -- http://mail.python.org/mailman/listinfo/python-list
Re: Switch statement
On 3/10/2013 11:18 AM, Steven D'Aprano wrote: On Sun, 10 Mar 2013 14:16:27 +, Joseph L. Casale wrote: I have a switch statement composed using a dict: switch = { 'a': func_a, 'b': func_b, 'c': func_c } switch.get(var, default)() As a result of multiple functions per choice, it migrated to: switch = { 'a': (func_a1, func_a2), 'b': (func_b1, func_b2), 'c': (func_c, ) } for f in switch.get(var, (default, )): f() As a result of only some of the functions now requiring unique arguments, I presume this needs to be migrated to a if/else statement? Is there a way to maintain the switch style with the ability in this scenario to cleanly pass args only to some functions? The dict-as-switch-statement pattern only works when the functions all take the same argument(s). Otherwise, you need to check which function you are calling, and provide the right arguments. If, for instance, the functions take either 0 or 1 arg and the 1 arg is always the same, an alternative to the other suggestions is to look at the signature in an if statement. In 3.3 this is relatively ease, as inspect.signature(func) returns a signature object. There are more complicated paths in earlier versions. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
RE: Switch statement
Or could you do something like: arguments_to_pass = [list of some sort] switch.get(var, default)(*arguments_to_pass) Stevens lambda suggestion was most appropriate. Within the switch, there are functions called with none, or some variation of arguments. It was not easy to pass them in after the fact, especially since the same function may have different args depending on which case. The lamda worked well. Thanks guys! jlc -- http://mail.python.org/mailman/listinfo/python-list
Attributions (was Re: switch)
In article mailman.1736.1260555724.2873.python-l...@python.org, Tim Chase python.l...@tim.thechases.com wrote: On 12/10/2009 09:22 PM, John Bokma wrote: Please don't delete attribution line(s), added: Asun Friere writes: I tend to prune them because a good newsreader will thread messages and put my reply in the context of the message to which I'm replying. You are assuming that everyone will get all messages. Even in this day of better network connections, that is an ill-founded assumption. Moreover, you have no assurance that the message will be read in the context of a newsgroup; consider someone forwarding a single message. Always always always provide attributions for quoting, it's just the Right Thing. -- Aahz (a...@pythoncraft.com) * http://www.pythoncraft.com/ Looking back over the years, after I learned Python I realized that I never really had enjoyed programming before. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
In article pan.2009.12.10.05.47...@remove.this.cybersource.com.au, Steven D'Aprano ste...@remove.this.cybersource.com.au wrote: On Wed, 09 Dec 2009 18:50:29 +, Nobody wrote: Compiled languages' switch statements typically require constant labels as this enables various optimisations. Pascal, for example, can test against either single values, enumerated values, or a range of values: case n of 0: writeln('zero'); 1, 2: writeln('one or two'); 3...10: writeln('something between three and ten'); else writeln('something different'); end; This shows where the merit of a switch/case statement lies. It guarantees both to the compiler and to the human reader that we are dealing with mutually exclusive and constant cases. This allows optimisation (c) and verification (h) advantages. A chain of elif's OTOH doesn't do that. On the top of my toes I will have to check every line whether the regularity breaks down. As regards polymorphism. It is dubious that an inherently different technique can be consistently and confidently promoted as an alternative. Sometimes it is, sometimes it isn't. Polymorphism is IMO promoted for far too much situations. As a maintenance programmer (being at least twice as smart as the people who wrote the original code) I can testify that code can be polymorphed to the point that it stops working and/or that it practically stops working and/or that it stops working practically. I'm the author of PostItFixup assembler. This assembler manages to assemble code with no control structures at all. 1] No IF, no FOR, no WHILE, no CASES. Nothing conditional, and no looping. How's that for a change? Although this is truly remarkable and well worth studying, I will not promote this style of programming as the ultimate alternative for everything. (And it breaks down at a point, sure.) Bottom line: Give to the Caesar what belongs to the Caesar... Not adding a switch to python is a matter of taste, good taste as far as I'm concerned. Adding a switch to C was also good taste, by the way. -- Steven Groetjes Albert -- 1] Only in the error checking there is an IF. -- Albert van der Horst, UTRECHT,THE NETHERLANDS Economic growth -- being exponential -- ultimately falters. alb...@spearc.xs4all.nl =n http://home.hccnet.nl/a.w.m.van.der.horst -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Bruno Desthuilliers: Well, obviously such business rules must by no mean be hardcoded. You really need a rule engine, configurable by your domain experts thru a DSL that we'll design specially for you. The rule engine will generate an AbstractScoreFactory that will instanciate appropriate IScore implementation objects that knows what to do. [snip] Thank you very much for bringing back some sanity in this newsgroup, sometimes a good antiexample like yours is better than many explanations. Bye, bearophile -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On 12/10/2009 09:22 PM, John Bokma wrote: Tim Chasepython.l...@tim.thechases.com writes: Please don't delete attribution line(s), added: Asun Friere writes: I tend to prune them because a good newsreader will thread messages and put my reply in the context of the message to which I'm replying. Both Thunderbird and Claws Mail seem to have correctly placed my message under Asun's message. However your reply to mine failed to show up under my message in either program (it showed up under the top-level post by Hong Zhang in both apps). Looks like you're sending from Gnus...a threading/reply bug in Gnus perhaps? Anyways...I'll leave them in for this reply. phone.update_from_record(record) This switch statement belongs to one guy. One guy who wants to know how to do everything that needs to be done to Phones no matter who asks This is where you make a false assumption -- the contents and parsing of the switch are provider-specific in this case, mapping to a common ontology of the Phone object: In that case, why not give the classes Asun suggested all the same base class: Phone? Whether the logic gets put in a subclass of Phone, or whether it gets put in a provider Phone-factory (as it currently does...the Provider superclass also knows how to auto-detect the format of a filename/path passed to it and know whether it can handle it), there's still a rat's-nest of if/else/switch type logic, each branch of which usually involves a single assignment, or further sub-branch checking. So I often have things that would pseudo-code like switch rectype: case '01': phone.textmessaging += row['txtmsgcost'] count = row['count'] switch subtype: case 'a': phone.textmessagessent += count case 'b': phone.textmessagesreceived += count case 'c': phone.pagessent += count case 'd': phone.pagesreceived += count case '02': ... which is fairly readable. However, with a method-dispatch dictionary, this flattens the hierarchy to defs at the same level (class definition scope), leaving the hierarchy visible only in the call-graph. Turning each of these a function would - obfuscate the flow and processing hierarchy - create a profusion of 1-3 line functions (about 50 Phone attributes, times currently about 15 provider formats, plus a duplication factor of about 10% where certain fields aggregate from various sources in the data, accumulating in a single Phone field) - have the overhead of several million function-calls Yes, having been programming since I was in middle-school (quick calculation yields a boy I'm old estimate of about 20 years...does anybody miss 360k 5.25 floppy disks? :) I do miss cassette tapes and the wheee kkkrggrggrgrgrg of a program loading. Heh, one of the other things I miss: booting my Apple ][+ and hitting the Reset button, resulting in a prompt where I could code in under 2 seconds from power-on. Can't say I miss tape at all though :) -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 11, 1:38 am, Tim Chase python.l...@tim.thechases.com wrote: It's clean if it were the solution to my problem Picking out that line first, just to be clear about this. You missed the disclaimer. This was never meant to be a solution to your problem. It was solution to the problem contained in the code you posted. Carl, asked a question, in response you provided an example, and I wrote a solution. I did so to in order to illustrate how something resembling a dispatch mechansism can save a programmer from ending up with a rat's-nest of elif chainage. I hope you did not misunderstand me as advocating your pulling apart working production code. Heck, I wouldn't, err ...don't, do this. Which is _not_ to say that it isn't actually a solution your problem as well! :) [One guy analogy] This is where you make a false assumption Again I don't really know your problem only the code you've posted. If I misunderstood the record types as originating from different providers, I'm sure you will find that my code, which faithfully reimplements yours, does not. -- the contents and parsing of the switch are provider-specific in this case, mapping to a common ontology of the Phone object: class MonopolyProvider1Parser: ... switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() class MonopolyProvider2Parser: ... switch row['recordtype']: case 'abc': phone.international += ( Decimal(row['canada cost']) + Decimal(row['eu cost']) + Decimal(row['mexico cost']) + Decimal(row['other intl cost']) ) case 'xyz': phone.text_messaging += int(row['textmessages']) ... default: raise WhatTheHeckIsThis() Fair enough. What you posted was a subset of your overall problem. Obviously! Inasmuch as the code that you posted accurately represents a subset of your problem, the solution given is still applicable, at least to that subset of your problem. It's just that each inidividual MonopolyProvider will require its own set of data sources. In any case, I'm sure you could work out it could be applied, if you put your mind to it. I agree this involves more code than the example required, possibly for less gain and I believe it is still advantageous to organise the code in a way which separates knowledge from logic. At least when that knowledge is non-trivial. # The one thing I'm sure I don't understand from the code is where the original rectypes comes into the process. Sorry, my worrying there about whether we need to look the appropriate RecType up in that dict was just a distraction. The problem isn't in the dict, but with that the try should only be trapping unknown types, not problems of instantiation. I should have written: try : AppropriateRecType = rectypes[rectype] except KeyError : raise WhatTheHeckIsThisError('unknown rectype: %s' % rectype) record = ApproriateRecType(row) From the provider data -- sometimes CSV files, sometimes tab-delimited text files, sometimes MS Access MDB files, sometimes a web service... varies per-provider (and some providers have multiple formats, like Verizon has MyBIZ and IBAS; ATT has their WinCD and Premier; etc). No two formats are the same, so the logic needed to parse the data into our internal homogenized Phone data structure varies per each one. And the logic (or lack thereof) used by many providers in creating their formats require reverse-engineering most of them through trial-and-error, and huge ugly if/elif/else chains. I feel your pain, I really do ... and a dispatch mechanism could relieve some of it. ;) Now I'm not saying you should implement it on extant production code. As I wrote above, I still use, and unfortunately maintain, older code which is a hideous mess of elif chains. The task of challenging these elif chains is daunting, and rewriting such working code won't rank in my work priorities for the foreseeable future. This is why, elif chains, when they first arise, or better perhaps, when they first begin to grow, should be examined to see whether they are a bud that ought to be nipped, whether they sensibly can be nipped, and if so how. They are, in Carl's words, red flags, at least they are if your're not a very good progammer, like me. I invite all my fellow NVGPs to treat them as such as well. :) I can compare extending and
Re: switch
On Dec 10, 2:00 pm, Carl Banks pavlovevide...@gmail.com wrote: On Dec 9, 5:02 pm, Asun Friere afri...@yahoo.co.uk wrote: On Dec 9, 7:08 pm, Carl Banks pavlovevide...@gmail.com wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? This would be a pertinent question, were I advocating that _all_ switch statements should, or even can, be replaced with dispatch using polymorphism. Then why did you claim that a decent OO should never have a switch statement then? The mere fact that it is possible to demonstrate a use of the 'goto' statement, which does not offend against a program's structural integrity, does not mean it's necessarily a good idea to have it lying about given that in the large majority of cases it leads to (encourages?) bad code. Python sagely declined to implement 'goto'. I feel the same considerations apply in regard to the switch/case statement in the context of a true* OO (ie python but not java ;). Imo the decision not to implement a switch statement was wise. This is not to deny that a traditional switch is not in often a sane solution. I just think that if your elifs are getting unwieldy enough to require the application of the proverbial layer of abstraction, then a switch statement fails to deliver sufficient abstraction. You argued that a decent language OO should never have a switch statement because polymorphic dispatch is the right way to handle it in OO languages, which implies that polymorphism can and should take the place of any switch statement. That is a misreading. I wrote, that the case logic is probably symptomatic of poor design. I advocated considering whether an OO solution might be more appropriate. You misunderstand my intent. I'm not here to postulate some ultimate OO truths, but to provide practical advice (aimed here mainly at Hong and Kee). In regard elif chains, this is my advice. If you see too many elifs in your code (or if you find yourself wishing for a switch statement) alarm bells should start to go off. STOP, give serious consideration as to whether applying some patterns or similar will improve the design, and HINT: first consider whether that pattern might be something resembling a dispatch mechanism, it's just downright spooky how in real-life programming situations this turns out to be the answer. Obviously the answers to these questions are not invariably 'yes.' Often enough they are. What if, instead of reading strings from a file, Why don't you answer my question first, Because, as I have already explained, I object to the question. It presupposes my holding a position I don't. But look perhaps I'm being unfair to you Carl. I presumed your question was rhetorical, or at least you supposed it disproved whatever it is you were attacking. If instead you were asking for clarification, the short answer is wrap as you read. A longer answer is in the response to Tim, I'll send in a while. cheers -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 10, 6:57 am, Tim Chase python.l...@tim.thechases.com wrote: Carl Banks wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? This is where I most miss a switch/case statement in Python...I do lots of text-file processing (cellular provider data), so I have lots of code (for each provider's individual format) that looks like phones = {} for row in csv.DictReader(file('data.txt', 'rb')): phonenumber = row['phonenumber'] if phonenumber not in phones: phones[phonenumber] = Phone(phonenumber) phone = phones[phonenumber] rectype = rectype if rectype == '01': phone.international += Decimal(row['internationalcost']) elif rectype == '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) elif rectype == ... ... else: raise WhatTheHeckIsThis() Great example Tim. This is something that many of us must be dealing with on a daily basis. The problem has enough details (bar one), to allow an answer and not so detailed as to be confusing. And for me it's a particularly good example, because your need accommodate mulitple provider formats makes me feel right at home. which would nicely change into something like switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() Cleaner yes. But, with respect, not so clean as to justify the construct. Following my advice you might express that switch statement like so: phone.update_from_record(record) It is, in this context, completely irrelevant observe that 'dispatch' originally referred specifically to the dismissal of ambassadors. It may be slightly more to the point to tap into the wisdom of Henry Ford and turn your design inside out. This switch statement belongs to one guy. One guy who wants to know how to do everything that needs to be done to Phones no matter who asks. Let's install a conveyor belt instead! Standard Disclaimer: Untested (obviously); just a sketch; I don't really know your problem only the code you've posted; etc etc. First some minimal architecture: --- #The first class your already have. We just need one more method class Phone (object) : ... def update_from_record (self, rec) : return rec.updatePhone(self) #and then some data source classes class RecType (dict) : def __init__ (self, row) : ... class RecType_001 (RecType) : def updatePhone(self, phone) : phone.interational += Decimal(self['internationalcost']) class RecType_002 (RecType) : def updatePhone(self, phone) : phone.text_messaging += ( int(self['textmessages sent']) + int(self['pages received']) + ... #and if we must ... rectypes = {'01':RecType_001, '02': RecType_002, ...} # The one thing I'm sure I don't understand from the code is where the original rectypes comes into the process. #I would prefer, if it's possible, just thowing the appropriate class in rather than looking up this dict to instantiate. --- Now the different providor types, previously the bane of your existence, are your staff. Your original code will now read something like: phones = {} for row in csv.DictReader(open('data.txt', 'rb')) : try : record = rectypes[rectype](row) except KeyError : raise WhatTheHeckIsThisError('unknown rectype: %s' % rectype) phonenumber = record.phonenumber if phonenumber not in phones : phones[phonenumber] = Phone(phonenumber) phone = phones[phonenumber] phone.update_from_record(record) I wonder if you agree that it's bit cleaner now? It's an effective solution. I'm making no representation that it's the best. I like think largely because it contains the knowledge accessibly. If you have lots of code that deal with this kind of thing, chances are library of core data source classage could reduce much of it to a simple (and legible!) one liner. A provider enhances their format, or a new provider format is added, code in one class, not in every switch they might be involved in. But sorry, I don't mean to patronise, I'm sure you know the spiel. Asun -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 10, 3:34 am, Asun Friere afri...@yahoo.co.uk wrote: On Dec 10, 2:00 pm, Carl Banks pavlovevide...@gmail.com wrote: [snip most of questionable, verly verbose reply] You argued that a decent language OO should never have a switch statement because polymorphic dispatch is the right way to handle it in OO languages, which implies that polymorphism can and should take the place of any switch statement. That is a misreading. I wrote, that the case logic is probably symptomatic of poor design. I advocated considering whether an OO solution might be more appropriate. You misunderstand my intent. I'm not here to postulate some ultimate OO truths, but to provide practical advice (aimed here mainly at Hong and Kee). In regard elif chains, this is my advice. Even granting that your post wasn't as drastic as it sounded (and enough people reacted to your first post that you should should probably consider whether it came off a little more strongly than you intended), I think you are still overstating it by a lot. OO polymorphic dispatching is good for some stuff, and simpler dispatching such with if...else, a dict, or a hypotheical switch, is good for some stuff. That's it. Having a bunch of if...elses is not probably wrong, and it's not a red flag, unless you're not a good programmer and have already missed a bunch of other more pertinent red flags. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Great example Tim. This is something that many of us must be dealing with on a daily basis. The problem has enough details (bar one), to allow an answer and not so detailed as to be confusing. And for me it's a particularly good example, because your need accommodate mulitple provider formats makes me feel right at home. which would nicely change into something like switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() Cleaner yes. But, with respect, not so clean as to justify the construct. Following my advice you might express that switch statement like so: phone.update_from_record(record) This switch statement belongs to one guy. One guy who wants to know how to do everything that needs to be done to Phones no matter who asks This is where you make a false assumption -- the contents and parsing of the switch are provider-specific in this case, mapping to a common ontology of the Phone object: class MonopolyProvider1Parser: ... switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() class MonopolyProvider2Parser: ... switch row['recordtype']: case 'abc': phone.international += ( Decimal(row['canada cost']) + Decimal(row['eu cost']) + Decimal(row['mexico cost']) + Decimal(row['other intl cost']) ) case 'xyz': phone.text_messaging += int(row['textmessages']) ... default: raise WhatTheHeckIsThis() # The one thing I'm sure I don't understand from the code is where the original rectypes comes into the process. From the provider data -- sometimes CSV files, sometimes tab-delimited text files, sometimes MS Access MDB files, sometimes a web service...varies per-provider (and some providers have multiple formats, like Verizon has MyBIZ and IBAS; ATT has their WinCD and Premier; etc). No two formats are the same, so the logic needed to parse the data into our internal homogenized Phone data structure varies per each one. And the logic (or lack thereof) used by many providers in creating their formats require reverse-engineering most of them through trial-and-error, and huge ugly if/elif/else chains. I wonder if you agree that it's bit cleaner now? It's an effective solution. I'm making no representation that it's the best. It's clean if it were the solution to my problem -- however, the mess comes from the profusion of provider formats. simple (and legible!) one liner. A provider enhances their format, or a new provider format is added, code in one class, not in every switch they might be involved in. But sorry, I don't mean to patronise, I'm sure you know the spiel. Yes, having been programming since I was in middle-school (quick calculation yields a boy I'm old estimate of about 20 years...does anybody miss 360k 5.25 floppy disks? :) and have my degree in CS. So it's not my lack of programming skill/knowledge, but rather your misunderstanding of the problem-space. Not to patronize ;-) -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Asun Friere wrote: On Dec 10, 2:00 pm, Carl Banks pavlovevide...@gmail.com wrote: On Dec 9, 5:02 pm, Asun Friere afri...@yahoo.co.uk wrote: On Dec 9, 7:08 pm, Carl Banks pavlovevide...@gmail.com wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? This would be a pertinent question, were I advocating that _all_ switch statements should, or even can, be replaced with dispatch using polymorphism. Then why did you claim that a decent OO should never have a switch statement then? You argued that a decent language OO should never have a switch statement because polymorphic dispatch is the right way to handle it in OO languages, which implies that polymorphism can and should take the place of any switch statement. That is a misreading. I wrote... [snip] You wrote, and I quote, For which reason python has no 'case' statement and why *no decent OO language should* . [emphasis added] Just to be clear. ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Thu, 10 Dec 2009 05:47:19 +, Steven D'Aprano wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This isn't what would normally be considered a switch (i.e. what C considers a switch). Anyone would think that C was the only programming language in existence... It's the only one I know of which calls such statements switch statements. Most other languages call them case statements. A switch tests the value of an expression against a set of constants. In C. Things may be different in other languages. For example, I recall the so-called 4GL (remember when that was the marketing term of choice for interpreted programming languages?) Hyperscript from Informix. I can't check the exact syntax right now, but it had a switch statement which allowed you to do either C-like tests against a single expression, or if-like multiple independent tests. Interpreted languages generally don't care about the labels being constant, so you can do e.g. (BBC BASIC V): CASE TRUE OF WHEN foo: blah WHEN bar: blah blah WHEN NOT(bar): blarg ENDCASE The test expression is compared against each case expression sequentially until one matches; both the test expression and case expressions are evaluated at run-time. This is essentially just an if/elif chain with different syntax, whereas a C-style switch may be signficiantly more efficient (e.g. using a jump table or a balanced tree). Compiled languages' switch statements typically require constant labels as this enables various optimisations. Pascal, for example, can test against either single values, enumerated values, or a range of values: case n of 0: writeln('zero'); 1, 2: writeln('one or two'); 3...10: writeln('something between three and ten'); else writeln('something different'); end; IOW, identical semantics to C, but with some extra syntax to avoid the need to write multiple consecutive labels. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Steven D'Aprano wrote: On Wed, 09 Dec 2009 18:50:29 +, Nobody wrote: On Tue, 08 Dec 2009 21:02:44 -0800, Kee Nethery wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This isn't what would normally be considered a switch (i.e. what C considers a switch). Anyone would think that C was the only programming language in existence... A switch tests the value of an expression against a set of constants. In C. Things may be different in other languages. For example, I recall the so-called 4GL (remember when that was the marketing term of choice for interpreted programming languages?) Hyperscript from Informix. I can't check the exact syntax right now, but it had a switch statement which allowed you to do either C-like tests against a single expression, or if-like multiple independent tests. Moving away from obsolete languages, we have Ruby which does much the same thing: if you provide a test value, the case expression does a C- like test against that expression, and if you don't, it does if-like multiple tests. http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what- you-can-do-with-it/ If you were writing the above in C, you would need to use a chain of if/else statements; you couldn't use a switch. Compiled languages' switch statements typically require constant labels as this enables various optimisations. Pascal, for example, can test against either single values, enumerated values, or a range of values: case n of 0: writeln('zero'); 1, 2: writeln('one or two'); 3...10: writeln('something between three and ten'); else writeln('something different'); end; Originally the 'case' statement in Pascal didn't support ranges or a default; they started as non-standard extensions in some implementations. Originally, if none of the values matched then that was a runtime error. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Tim Chase python.l...@tim.thechases.com writes: Please don't delete attribution line(s), added: Asun Friere writes: phone.update_from_record(record) This switch statement belongs to one guy. One guy who wants to know how to do everything that needs to be done to Phones no matter who asks This is where you make a false assumption -- the contents and parsing of the switch are provider-specific in this case, mapping to a common ontology of the Phone object: In that case, why not give the classes Asun suggested all the same base class: Phone? I wonder if you agree that it's bit cleaner now? It's an effective solution. I'm making no representation that it's the best. It's clean if it were the solution to my problem -- however, the mess comes from the profusion of provider formats. Yup, and there is no other solution to that than to convert them to something universal. Yes, having been programming since I was in middle-school (quick calculation yields a boy I'm old estimate of about 20 years...does anybody miss 360k 5.25 floppy disks? :) I do miss cassette tapes and the wheee kkkrggrggrgrgrg of a program loading. -- John Bokma Read my blog: http://johnbokma.com/ Hire me (Perl/Python): http://castleamber.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 8, 9:36 pm, Asun Friere afri...@yahoo.co.uk wrote: This code is probably symptomatic of poor design. (Not to mention that your condition tests). For which reason python has no 'case' statement and why no decent OO language should. It is a principle of OO design that an object should know what to do itself. Rather running an object though a series of tests, it is better to send the object a message, relying on polymorphism or duck- typing, and deal with any exceptions thrown. What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Steven D'Aprano a écrit : On Tue, 08 Dec 2009 21:36:23 -0800, Asun Friere wrote: (snip) It is a principle of OO design that an object should know what to do itself. Rather running an object though a series of tests, it is better to send the object a message, relying on polymorphism or duck- typing, and deal with any exceptions thrown. But putting that aside, I find myself wondering how you would deal with the following switch-like series of tests. def print_grades(score): if not 0 = score = 100: raise ValueError(score must be between 0 and 100) if score 50: print You have failed. consider_suspension() elif score == 50: print You have just passed by the skin of your teeth. elif score 60: print You have scored a D. You need to try harder. elif score 70: print You have scored a C. elif score 80: print You have scored a B. Well done. elif score 100: print Congratulations, you have scored an A. else: assert score == 100 print You have scored a PERFECT 100% SCORE!!! if not evidence_of_cheating(): call_newspapers() Well, obviously such business rules must by no mean be hardcoded. You really need a rule engine, configurable by your domain experts thru a DSL that we'll design specially for you. The rule engine will generate an AbstractScoreFactory that will instanciate appropriate IScore implementation objects that knows what to do. You also need to decouple the output mechanism - what if you need to output to a web page, an IPhone app, a RSS stream, an audio stream or clay tablets ? To allow for maximum decoupling, the output mechanism should be configurable thru a strict, well defined and universally understood language - I mean XML, of course. Obviously that could, with a non-trivial amount of work, be turned into a dictionary dispatch, Dictionnary dispatch ? C'mon, you must be joking ? An enterprise application is not some QD cowboy script, you know ? You do have to apply state of the art designs and patterns to do it properly g -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
hong zhang henryzhang62 at yahoo.com writes: List, Python does not have switch statement. Any other option does similar work? Thanks for help. --henry I see a couple of people have mentioned using a dictionary. If the value that you are switching on is a string, or could be made into one, you can use a variant of the command dispatch pattern. class MyCommandDispatcher(object): def do_a(self): # do stuff def do_b(self): # do stuff def do_5(self): # do stuff def default(self): # do stuff def switch(self, option): getattr(self, 'do_' + str(option), self.default)() d = MyCommandDispatcher() d.switch('a') d.switch(5) This isn't _much_ more coding than using the dictionary method, and is pretty readable. This is also a common pattern in python. Matt -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Tue, 08 Dec 2009 21:02:44 -0800, Kee Nethery wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This isn't what would normally be considered a switch (i.e. what C considers a switch). A switch tests the value of an expression against a set of constants. If you were writing the above in C, you would need to use a chain of if/else statements; you couldn't use a switch. Compiled languages' switch statements typically require constant labels as this enables various optimisations. The above construct is equivalent to Lisp's cond, or guards in some functional languages. While switch-like constructs can be implemented with a dictionary, cond-like constructs would have to be implemented with a list, as there's no guarantee that the tests are mutually exclusive, so the order is significant. E.g. rules = [((lambda (foo, bar): return foo), (lambda: blah)), ((lambda (foo, bar): return bar), (lambda: blah blah)), ((lambda (foo, bar): return not bar), (lambda: blarg)), ...] for test, action in rules: if test(foo, bar): action() break -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Carl Banks wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? This is where I most miss a switch/case statement in Python...I do lots of text-file processing (cellular provider data), so I have lots of code (for each provider's individual format) that looks like phones = {} for row in csv.DictReader(file('data.txt', 'rb')): phonenumber = row['phonenumber'] if phonenumber not in phones: phones[phonenumber] = Phone(phonenumber) phone = phones[phonenumber] rectype = rectype if rectype == '01': phone.international += Decimal(row['internationalcost']) elif rectype == '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) elif rectype == ... ... else: raise WhatTheHeckIsThis() which would nicely change into something like switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() This doesn't convert well (i.e. compactly) to a dictionary-dispatch idiom. :( -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Tim Chase wrote: Carl Banks wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? [snip] which would nicely change into something like switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() This doesn't convert well (i.e. compactly) to a dictionary-dispatch idiom. :( Shouldn't 'case' be indented to the same level as 'switch'? And 'default' could be replaced by 'else' without ambiguity. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
MRAB wrote: Tim Chase wrote: switch row['recordtype']: case '01': phone.international += Decimal(row['internationalcost']) // optionally a break here depending on // C/C++/Java/PHP syntax vs. Pascal syntax which // doesn't have fall-through case '02': phone.text_messaging += ( int(row['textmessages sent']) + int(row['pages received']) + int(row['textmessages sent']) + int(row['pages received']) ... default: raise WhatTheHeckIsThis() This doesn't convert well (i.e. compactly) to a dictionary-dispatch idiom. :( Shouldn't 'case' be indented to the same level as 'switch'? And 'default' could be replaced by 'else' without ambiguity. But I want a GREEN bike-shed! :-) Yeah, else works nicely and makes sense. Indentation could go either way in my book, but I lean towards indented case because the switch can get easily lost if the cases aren't indented: switch foo: case 1: stuff() case 2: morestuff() switch bar: case 3: whatever() case 4: yet_more() else: whip_it() vs switch foo: case 1: stuff() case 2: morestuff() switch bar: case 3: whatever() case 4: yet_more() else: whip_it() Just my ponderings... -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 9, 5:39 pm, Steven D'Aprano ste...@remove.this.cybersource.com.au wrote: On Tue, 08 Dec 2009 21:36:23 -0800, Asun Friere wrote: On Dec 9, 4:02 pm, Kee Nethery k...@kagi.com wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This code is probably symptomatic of poor design. (Not to mention that your condition tests). For which reason python has no 'case' statement and why no decent OO language should. That's a provocative statement. My reply was lost in the aether, so here goes again. If it's provocative, it is at least hedged. It is merely symptomatic and only probably so, because there are numerous instances where case logic is the only sensible solution. I'm not advocating some cargo- cult rule for the elimination of all uses of elif. If I were I would rightly be presented with numerous code examples where a switch is a sensible option, much as happens when someone pronounces against the humble goto statement. It is a principle of OO design that an object should know what to do itself. Rather running an object though a series of tests, it is better to send the object a message, relying on polymorphism or duck- typing, and deal with any exceptions thrown. Perhaps that's true, but you'll note that the example given above doesn't run a single object through a series of tests, but runs a series of tests on DIFFERENT objects, to find the first which matches. Well actually two objects with one being tested twice. But you are right, I was being sloppy when I wrote running an object especially in light of the fact that the following clause makes more sense when run against objects of potentially different class. Same for dispatch mechanisms of course. What I'm saying is that when you find a large if/elif/else in your code, regard it with suspicion and consider whether better design might not eliminate it. And I'm speaking as someone who still has to maintain some code (in perl not python) which has an if/elif/else statement spanning 5 A4 pages. What's worse, I was the one who did this to myself some 8 years ago. What I'm also saying is learn about dispatch mechanisms, they are about the most useful patterns out there (next to the State pattern). As a matter of practice I have found that more often than not, large case statements can better be solved using double-dispatch. Obviously not all. Obviously! But putting that aside, I find myself wondering how you would deal with the following switch-like series of tests. def print_grades(score): if not 0 = score = 100: raise ValueError(score must be between 0 and 100) if score 50: print You have failed. consider_suspension() elif score == 50: print You have just passed by the skin of your teeth. elif score 60: print You have scored a D. You need to try harder. elif score 70: print You have scored a C. elif score 80: print You have scored a B. Well done. elif score 100: print Congratulations, you have scored an A. else: assert score == 100 print You have scored a PERFECT 100% SCORE!!! if not evidence_of_cheating(): call_newspapers() Obviously that could, with a non-trivial amount of work, be turned into a dictionary dispatch, but is the benefit worth the extra effort? Probably not. Depending on the nature of the app, I'd probably be calling score.print_grades() and using cutoff values of 85, 75, 60 and 50 (perhaps not even hardcoded into the logic), but sure this is a fine example of a place where a solution other than a simple switch would be overkill. As such this example would be a good counter to the absolute repudiation of case logic I did not make. I doubt, however, that it is of great pedagogic value in alerting programmers to the design options available to them in overcomming what the perceive as a lack in the language. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 9, 7:08 pm, Carl Banks pavlovevide...@gmail.com wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? This would be a pertinent question, were I advocating that _all_ switch statements should, or even can, be replaced with dispatch using polymorphism. What if, instead of reading strings from a file, you are parsing, say xml, into an object framework isomorphic to the file's schema? And no, this is not a contrived example. Now you want to print out the structure, or a branch thereof. To make matters interesting you want to be able to print it out in a number of different formats. So we have: 5 def print_out (element, fmnt) : 6 if element.__class__ is schema.Title : 7 if str(fmnt) == 'html' : 8 print_out_spam_title(element) 9 elif str(fmnt) == 'txt' : 10 print_out_ham_title(element) 11 elif 12 elif element.__class__ is schema.Paragraph : 13 if str(fmnt) == 'html' : 14 print_out_spam_paragraph(element) 15 elif str(fmnt) == 'txt' : 16 print_out_ham_paragraph(element) 17 elif ... 18 elif element.__class__ is ... 19 ... 20 And so on for a dozen or so tags and 3 formats. And imagine the joy of adding the 4th or 5th format. Now I guess you already realise that applying a dispatch mechanism here will improve the design and result in code that is dryer, far more easily extensible and arguably (but only arguably) more readible? -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 9, 5:02 pm, Asun Friere afri...@yahoo.co.uk wrote: On Dec 9, 7:08 pm, Carl Banks pavlovevide...@gmail.com wrote: What if the object is a string you just read from a file? How do you dispatch using polymorphism in that case? This would be a pertinent question, were I advocating that _all_ switch statements should, or even can, be replaced with dispatch using polymorphism. Then why did you claim that a decent OO should never have a switch statement then? You argued that a decent language OO should never have a switch statement because polymorphic dispatch is the right way to handle it in OO languages, which implies that polymorphism can and should take the place of any switch statement. What if, instead of reading strings from a file, Why don't you answer my question first, then I'll entertain whatever point you are trying to make with this example? Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Wed, 09 Dec 2009 18:50:29 +, Nobody wrote: On Tue, 08 Dec 2009 21:02:44 -0800, Kee Nethery wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This isn't what would normally be considered a switch (i.e. what C considers a switch). Anyone would think that C was the only programming language in existence... A switch tests the value of an expression against a set of constants. In C. Things may be different in other languages. For example, I recall the so-called 4GL (remember when that was the marketing term of choice for interpreted programming languages?) Hyperscript from Informix. I can't check the exact syntax right now, but it had a switch statement which allowed you to do either C-like tests against a single expression, or if-like multiple independent tests. Moving away from obsolete languages, we have Ruby which does much the same thing: if you provide a test value, the case expression does a C- like test against that expression, and if you don't, it does if-like multiple tests. http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what- you-can-do-with-it/ If you were writing the above in C, you would need to use a chain of if/else statements; you couldn't use a switch. Compiled languages' switch statements typically require constant labels as this enables various optimisations. Pascal, for example, can test against either single values, enumerated values, or a range of values: case n of 0: writeln('zero'); 1, 2: writeln('one or two'); 3...10: writeln('something between three and ten'); else writeln('something different'); end; -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Tue, Dec 8, 2009 at 5:53 PM, hong zhang henryzhan...@yahoo.com wrote: Python does not have switch statement. Any other option does similar work? Yes, a dictionary with functions as values: http://simonwillison.net/2004/May/7/switch/ Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Tue, Dec 8, 2009 at 8:53 PM, hong zhang henryzhan...@yahoo.com wrote: List, Python does not have switch statement. Any other option does similar work? Thanks for help. Use a dict instead, where the keys are the different cases and the values are usually callable objects (such as functions) options = {a : do_a, b,do_b, c, do_c} option = a try : options[option]() except KeyError : do_default() --henry -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 9, 1:00 pm, Benjamin Kaplan benjamin.kap...@case.edu wrote: On Tue, Dec 8, 2009 at 8:53 PM, hong zhang henryzhan...@yahoo.com wrote: List, Python does not have switch statement. Any other option does similar work? Thanks for help. Use a dict instead, where the keys are the different cases and the values are usually callable objects (such as functions) options = {a : do_a, b,do_b, c, do_c} option = a try : options[option]() except KeyError : do_default() --henry -- http://mail.python.org/mailman/listinfo/python-list Even better (well, shorter!): options = {a : do_a, b,do_b, c, do_c} options.get(option, do_default)() Ross -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
Even better (well, shorter!): options = {a : do_a, b,do_b, c, do_c} options.get(option, do_default)() You can also make it something callable like so, which is a little more compact if you need to reuse it a lot: def do_a(x): print a:, x ... def do_b(x): print b:, x ... def do_c(x): print c:, x ... do_something = {a:do_a, b:do_b, c: do_c}.get do_something('a')(4) a: 4 do_something('c')(5) c: 5 do_something built-in method get of dict object at 0x6de40 do_something('d') do_something('d')(5) Traceback (most recent call last): File stdin, line 1, in module TypeError: 'NoneType' object is not callable -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 9, 4:02 pm, Kee Nethery k...@kagi.com wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This code is probably symptomatic of poor design. (Not to mention that your condition tests). For which reason python has no 'case' statement and why no decent OO language should. It is a principle of OO design that an object should know what to do itself. Rather running an object though a series of tests, it is better to send the object a message, relying on polymorphism or duck- typing, and deal with any exceptions thrown. Generally if you find yourself wanting to use a 'case' statement or writing a series of if/elif which involves more than say, three, elifs, condsider whether you cannot use a a href=http:// peak.telecommunity.com/protocol_ref/dispatch-example.htmldouble dispatch/a mechanism instead. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Tue, 08 Dec 2009 21:02:44 -0800, Kee Nethery wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif Are you sure you want to test for equality with True and False? Generally one should write that as: if foo: blah elif bar: blah blah elif not bar: blarg ... -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Tue, 08 Dec 2009 21:36:23 -0800, Asun Friere wrote: On Dec 9, 4:02 pm, Kee Nethery k...@kagi.com wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif This code is probably symptomatic of poor design. (Not to mention that your condition tests). For which reason python has no 'case' statement and why no decent OO language should. That's a provocative statement. It is a principle of OO design that an object should know what to do itself. Rather running an object though a series of tests, it is better to send the object a message, relying on polymorphism or duck- typing, and deal with any exceptions thrown. Perhaps that's true, but you'll note that the example given above doesn't run a single object through a series of tests, but runs a series of tests on DIFFERENT objects, to find the first which matches. But putting that aside, I find myself wondering how you would deal with the following switch-like series of tests. def print_grades(score): if not 0 = score = 100: raise ValueError(score must be between 0 and 100) if score 50: print You have failed. consider_suspension() elif score == 50: print You have just passed by the skin of your teeth. elif score 60: print You have scored a D. You need to try harder. elif score 70: print You have scored a C. elif score 80: print You have scored a B. Well done. elif score 100: print Congratulations, you have scored an A. else: assert score == 100 print You have scored a PERFECT 100% SCORE!!! if not evidence_of_cheating(): call_newspapers() Obviously that could, with a non-trivial amount of work, be turned into a dictionary dispatch, but is the benefit worth the extra effort? Generally if you find yourself wanting to use a 'case' statement or writing a series of if/elif which involves more than say, three, elifs, condsider whether you cannot use a a href=http:// peak.telecommunity.com/protocol_ref/dispatch-example.htmldouble dispatch/a mechanism instead. I don't see how a series of tests on a single object is comparable to the double-dispatch example given. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: switch
On Dec 9, 5:12 pm, Steven D'Aprano ste...@remove.this.cybersource.com.au wrote: On Tue, 08 Dec 2009 21:02:44 -0800, Kee Nethery wrote: I string together a bunch of elif statements to simulate a switch if foo == True: blah elif bar == True: blah blah elif bar == False: blarg elif Are you sure you want to test for equality with True and False? Generally one should write that as: if foo: blah elif bar: blah blah elif not bar: blarg ... -- Steven I was going to point that out, but thought it a little OT. One might also mention that testing for if foo is None : is a special case. I'm also having a bit of a problem imagining what the subsequent conditions must be which make testing elif not bar subsequent to testing elif bar necessary, but that's just me. Back OT, one would hope not to encounter python code with a long chain of elifs like that. Probably the design should be improved, or where this would be overkill, use the dictionary trick. -- http://mail.python.org/mailman/listinfo/python-list
Re: switch to interactive mode
On Mon, 16 Mar 2009 23:49:34 +0100, nntpman68 wrote: I'd like, that a python script can be started by just calling it (clicking on it), but that the script can decide to enter interactive mode if certain conditions occur. Is this possible? Don't know about the clicky-clicky part, but I've used code.interact to do something similar. JBW -- http://mail.python.org/mailman/listinfo/python-list
Re: switch to interactive mode
On Mar 16, 5:49 pm, nntpman68 news1...@free.fr wrote: Hi I know about two ways to enter python interactive mode 1.) just start python 2.) run python -i pythonscript.py What I am looking for is slightly different: I'd like, that a python script can be started by just calling it (clicking on it), but that the script can decide to enter interactive mode if certain conditions occur. Is this possible? That sounds kind of like needing to embed the interpreter. I would recommend looking into that. Wingware's Wing IDE has this feature where you can run the program up a breakpoint and then use their debugger to interact with the variables and objects and such. Mike -- http://mail.python.org/mailman/listinfo/python-list
Re: switch to interactive mode
Hi JBW. code.interact() does what I wanted. Great !!! Thanks N JBW wrote: On Mon, 16 Mar 2009 23:49:34 +0100, nntpman68 wrote: I'd like, that a python script can be started by just calling it (clicking on it), but that the script can decide to enter interactive mode if certain conditions occur. Is this possible? Don't know about the clicky-clicky part, but I've used code.interact to do something similar. JBW -- http://mail.python.org/mailman/listinfo/python-list
Re: switch user
Check out the os module, especially the os.getgid(), os.getuid(), os.setgid(), os.getuid(), methods. There are more , take at a look at Python documentation. You can start a script as root then change your priveleges with os.setgid() os.setuid() methods. Note: those methods operate with integer user and group IDs, not with user and group names. Hope that helps, -Nick Vatamaniuc [EMAIL PROTECTED] wrote: hi due to certain constraints, i will running a python script as root inside this script, also due to some constraints, i need to switch user to user1 to run the rest of the script...is there a way ?thanks -- http://mail.python.org/mailman/listinfo/python-list
Re: Switch statement (was: Lambda going out of fashion)
Skip Montanaro [EMAIL PROTECTED] wrote in news:[EMAIL PROTECTED]: Stephen { Stephen 'one': lambda x:x.blat(), Stephen 'two': lambda x:x.blah(), Stephen }.get(someValue, lambda x:0)(someOtherValue) One thing to remember is that function calls in Python are pretty damn expensive. If x.blat() or x.blah() are themselves only one or two lines of code, you might find that your switch statement is better written as an if/elif/else statement. You're making potentially three function calls (get(), lambda and x.blat() or x.blah()) to perform what might only be a small handful of inline statements. I'll ignore the readability cost of your solution vs. an if statement. Stephen So, the questions I am asking are: Is this okay with everyone? Sure. I'll adjust. Stephen Does anyone else feel that lambda is useful in this kind of Stephen context? It's useful in this sort of context. It will probably always be limited to single expressions, which will always leave it a second-class citizen in Python. Interestingly enough, lambda in the Lisp world has the same limitation, however, since Lisp code is nothing but a series of s-expressions, that's not a problem. Stephen Are there alternatives I have not considered? I've never seen a situation where if/elif/else wasn't adequate or was less clear than the many attempts at switch-like behavior. Folks (in general), there is still an open PEP on a switch statement for Python. It's been idle since late 2001: http://www.python.org/peps/pep-0275.html It would help if interested people were to take a look at it and identify open issues. If you google for pep 275 you will probably find relevant python-dev discussions from the 2001/2002 timeframe. Thomas Wouters' patch for the interpreter would also need to be resurrected and brought up-to-date. I not longer remember why the PEP stalled. It seems to me that it was regarded as misguidod. -- rzed -- http://mail.python.org/mailman/listinfo/python-list