Re: Switch function

2019-02-03 Thread Dan Sommers

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

2019-02-03 Thread Avi Gross
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

2019-02-03 Thread Dan Sommers

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

2013-03-10 Thread Steven D'Aprano
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

2013-03-10 Thread Joseph L. Casale
 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

2013-03-10 Thread Mitya Sirenef

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

2013-03-10 Thread Nicholas Cole
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

2013-03-10 Thread Terry Reedy

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

2013-03-10 Thread Joseph L. Casale
 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)

2009-12-24 Thread Aahz
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

2009-12-21 Thread Albert van der Horst
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

2009-12-11 Thread Bearophile
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

2009-12-11 Thread Tim Chase

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

2009-12-11 Thread Asun Friere
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

2009-12-10 Thread Asun Friere
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

2009-12-10 Thread Asun Friere
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

2009-12-10 Thread Carl Banks
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

2009-12-10 Thread Tim Chase

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

2009-12-10 Thread Ethan Furman

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

2009-12-10 Thread Nobody
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

2009-12-10 Thread MRAB

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

2009-12-10 Thread John Bokma
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

2009-12-09 Thread Carl Banks
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

2009-12-09 Thread Bruno Desthuilliers

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

2009-12-09 Thread Matt McCredie
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

2009-12-09 Thread Nobody
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

2009-12-09 Thread Tim Chase

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

2009-12-09 Thread MRAB

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

2009-12-09 Thread Tim Chase

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

2009-12-09 Thread Asun Friere

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

2009-12-09 Thread Asun Friere
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

2009-12-09 Thread Carl Banks
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

2009-12-09 Thread Steven D'Aprano
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

2009-12-08 Thread Chris Rebert
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

2009-12-08 Thread Benjamin Kaplan
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

2009-12-08 Thread rzzzwilson
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

2009-12-08 Thread zeph

 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

2009-12-08 Thread Kee Nethery
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

2009-12-08 Thread Asun Friere
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

2009-12-08 Thread Steven D'Aprano
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

2009-12-08 Thread Steven D'Aprano
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

2009-12-08 Thread Asun Friere
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

2009-03-16 Thread JBW
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

2009-03-16 Thread Mike Driscoll
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

2009-03-16 Thread nntpman68

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

2006-10-03 Thread Nick Vatamaniuc
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)

2004-12-23 Thread rzed
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