Python is a language designed around simplicity. It has relatively few keywords and doesn't support all the latest clever gubbins that you'll find in languages such as Scala and Ruby, which is probably why it is finding great success as an introductory teaching language: a simple syntax that introduces beginnners Though it is missing many of the newer language constructs, Python can still do anything that Ruby and Scala will do; it just might take you a little longer to code, that's all. :-)
A case (if you'll excuse the expression) in point is the case statement. Most languages, like Java, have one:
public class SwitchDemo {
public static void main(String[] args) {
int month = 8;
String monthString;
switch (month) {
case 1: monthString = "January";
break;
case 2: monthString = "February";
break;
case 3: monthString = "March";
break;
case 4: monthString = "April";
break;
case 5: monthString = "May";
break;
case 6: monthString = "June";
break;
case 7: monthString = "July";
break;
case 8: monthString = "August";
break;
case 9: monthString = "September";
break;
case 10: monthString = "October";
break;
case 11: monthString = "November";
break;
case 12: monthString = "December";
break;
default: monthString = "Invalid month";
break;
}
System.out.println(monthString);
}
}
And so does Ruby.
# Print the eighth month
month = 8
case month
when 1
month_string = 'January'
when 2
month_string = 'February'
when 3
month_string = 'March'
when 4
month_string = 'April'
when 5
month_string = 'May'
when 6
month_string = 'June'
when 7
month_string = 'July'
when 8
month_string = 'August'
when 9
month_string = 'September'
when 10
month_string = 'October'
when 11
month_string = 'November'
when 12
month_string = 'December'
else
month_string = 'Invalid month'
end
print month_string
But Python doesn't.
:-(
Python's designer wanted to leave out everything that was superfluous, and when you get right down to it, the case
statement is nothing more than a thin veneer over an if...elseif...else
statement. So here's how you do it in Python:
month = 8
if month == 1:
monthString = "January"
elif month == 2:
monthString = "February"
elif month == 3:
monthString = "March"
# I'm pretty sure you get the picture ...
else:
monthString = "Invalid month"
print monthString
Yes, it's not particulary exciting, but by the same token it also doesn’t hold any nasty surprises. Java's switch...case
statement has copied the peculiar convention from the C language that allows you to fall through to the next case by leaving out the break
statement.
public class SwitchDemo {
public static void main(String[] args) {
int month = 8;
String monthString;
switch (month) {
case 1: monthString = "January";
break;
case 2: monthString = "February";
break;
case 3: monthString = "March";
break;
case 4: monthString = "April";
/* break; */
case 5: monthString = "May";
break;
case 6: monthString = "June";
break;
case 7: monthString = "July";
break;
case 8: monthString = "August";
break;
case 9: monthString = "September";
break;
case 10: monthString = "October";
break;
case 11: monthString = "November";
break;
case 12: monthString = "December";
break;
default: monthString = "Invalid month";
break;
}
System.out.println(monthString);
}
}
This example will give us
April
May
Now there are some case where this might be useful, but I can't help thinking that if you want to do something like this then you should be using a different code structure entirely to make it obvious why. Even though switch...case
statements are usually created through repeated copy/pasting, I still run across many cases where a bug is introduced because of a missing break
.
Still, many believe that the Python way of doing things is needlessly verbose, and I suppose it is, which is why I tend to shy away from rambling if...else
structures whenever possible, because in Python (and indeed Ruby) there is a much better way.
If you read that piece I did on my Alfred Date workflow then you'll know I make heavy use of dictionaries to keep the code tight and maintainable.
month = 8
month_map = {
1: "January",
2: "February",
3: "March",
4: "April",
5: "May",
6: "June",
7: "July",
8: "August",
9: "September",
10: "October",
11: "November",
12: "December"
}
print month_map[month] if month in month_map else "Invalid month"
Much neater I'm sure you'll agree.
That's all very well for printing out simple strings, but the case
statement is often used for executing code. Not a problem with Python (or Ruby for that matter) since the language can pass simple blocks of code around as they were data. Now, I'm going to deliberately overcomplicate things here, so remember it's just a demo!
from __future__ import print_function
month = 8
month_map = {
1: lambda: print ("January"),
2: lambda: print("February"),
3: lambda: print("March"),
4: lambda: print("April"),
5: lambda: print("May"),
6: lambda: print("June"),
7: lambda: print("July"),
8: lambda: print("August"),
9: lambda: print("September"),
10: lambda: print("October"),
11: lambda: print("November"),
12: lambda: print("December")
}
month_map[month]() if month in month_map else print("Invalid month")
The change here is that we put the code to be executed (the print
) inside the map, rather than simply supplying a string. The lambda
statement marks the map data as a function that can be executed. Note that we have also added brackets to the month_map[month]
call to indicate that the map entry can be executed as code, and is not simply a data item.
All very wonderful, but there are caveats:
- Lambda statements can only be single line expressions that return a value. This is why we have imported a specialist print function from Python 3. The standard print function is a simple procedure without a return value.
- You want a more complex function? Then you might need to create a separate
def
for each entry in the map, though you can perhaps alleviate this with a bit of judicious currying
Comments
comments powered by Disqus