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