Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Choosing between different switch-case replacements in Python - dictionary or if-elif-else?

I recently read the questions that recommend against using switch-case statements in languages that do support it. As far as Python goes, I've seen a number of switch case replacements, such as:

  1. Using a dictionary (Many variants)
  2. Using a Tuple
  3. Using a function decorator (http://code.activestate.com/recipes/440499/)
  4. Using Polymorphism (Recommended method instead of type checking objects)
  5. Using an if-elif-else ladder
  6. Someone even recommended the Visitor pattern (Possibly Extrinsic)

Given the wide variety of options, I am having a bit of difficulty deciding what to do for a particular piece of code. I would like to learn the criteria for selecting one of these methods over the other in general. In addition, I would appreciate advice on what to do in the specific cases where I am having trouble deciding (with an explanation of the choice).

Here is the specific problem:
(1)

def _setCurrentCurve(self, curve):
        if curve == "sine":
            self.currentCurve =  SineCurve(startAngle = 0, endAngle = 14,
            lineColor = (0.0, 0.0, 0.0), expansionFactor = 1,
            centerPos = (0.0, 0.0))
        elif curve == "quadratic":
            self.currentCurve = QuadraticCurve(lineColor = (0.0, 0.0, 0.0))

This method is called by a qt-slot in response to choosing to draw a curve from a menu. The above method will contain a total of 4-7 curves once the application is complete. Is it justified to use a throw away dictionary in this case? Since the most obvious way to do this is if-elif-else, should I stick with that? I have also consider using **kargs here (with a friends help) since all the curve classes use **kargs...

(2)
This second piece of code is a qt-slot that is called when the user changes a property of a curve. Basically the slot takes the data from the gui (spinBox) and puts it in an instance variable of the appropriate curve class. In this case, I again have the same question - should I use a dict?

Here is the aforementioned slot-

def propertyChanged(self, name, value):
    """A Qt slot, to react to changes of SineCurve's properties."""
    if name == "amplitude":
        self.amplitude = value
    elif name == "expansionFactor":
        self.expansionFactor = value
    elif name == "startAngle":
        self.startAngle = value
    elif name == "endAngle":
        self.endAngle = value  

For reference, here is the code for connecting to the above slot -

def _connectToPage(self, page):
    for connectionData in page.getConnectibles():
        self.connect(connectionData["object"],
                    SIGNAL(connectionData["signal"]),
                    lambda value, name = connectionData["property"]:\
                        self.currentCurve.propertyChanged(name, value))
        self.connect(connectionData["object"],
                    SIGNAL(connectionData["signal"]),
                    self.hackedDisplayArea.update) 

Note - The self.endAngle etc. are initialized in the constructor.

As far as I know, the reasons for choosing a dict is for fast lookup. When is that warranted? when I have 100 cases or more? Is it a good idea to keep building and throwing away a dictionary each time the function is called? If I build a dict for this purpose outside a function, should I check If it is needed elswhere? What happens if it is not needed elsewhere?

My question is what is the best-practice if there is one? What is the best/most elegant way to go about things? Put in yet another way, when to use if-elif-else, when to use each of the other options?

like image 646
batbrat Avatar asked Feb 27 '09 11:02

batbrat


People also ask

What can I use instead of a switch case in python?

What is the replacement of Switch Case in Python? Unlike every other programming language we have used before, Python does not have a switch or case statement. To get around this fact, we use dictionary mapping.

Does Python support switch or case statement in Python if not what is the reason for the same?

Unlike C++, Java, Ruby, and other programming languages, Python does not provide a switch case statement, but it offers few workarounds to make this statement work. For example, Python allows you to create your code snippets that work like Python Switch case statements in the other programming languages.

Does Python have a switch statement if so how is it implemented if not are there ways to implement it do other languages offer a switch statement?

Well, the answer to this question is NO. Unlike any other programming language, python language does not have switch statement functionality.

How many types of switch cases in Python?

Then we know that python doesn't have its built-in switch case statements. After that, we learn three different ways to implement switch cases in python.


2 Answers

In the first example I would certainly stick with the if-else statement. In fact I don't see a reason not to use if-else unless

  1. You find (using e.g. the profile module) that the if statement is a bottleneck (very unlikely IMO unless you have a huge number of cases that do very little)

  2. The code using a dictionary is clearer / has less repetition.

Your second example I would actually rewrite

setattr(self, name, value)

(probably adding an assert statement to catch invalid names).

like image 26
dF. Avatar answered Oct 23 '22 13:10

dF.


Sigh. Too much hand-wringing over the wrong part of the problem. The switch statement is not the issue. There are many ways of expressing "alternative" that don't add meaning.

The issue is meaning -- not technical statement choices.

There are three common patterns.

  • Mapping a key to an object. Use a dictionary if it is almost totally static and you have a mapping between a simple key and another more complex thing. Building a dictionary on the fly each time you need it is silly. You can use this if it's what you mean: your "conditions" are simple, static key values that map to objects.

  • Variant behavior among subclasses. Use Polymorphism instead of type checking objects. Correct. If you have similar objects in multiple classes with variant behavior, they should be polymorphic. Use this as often as possible.

  • Other variant behavior. Use an if-elif-else ladder. Use this when you don't have largely static key-to-value mapping. Use this when the conditions are complex, or you mean procedures, not objects.

Everything else is just tricky code that can achieve similar results.

Using a Tuple. This is just dictionary without the mapping. This requires search, and search should be avoided whenever possible. Don't do this, it's inefficient. Use a dictionary.

Using a function decorator (http://code.activestate.com/recipes/440499/). Icky. This conceals the if-elif-elif nature of the problem you're solving. Don't do this, it isn't obvious that the choices are exclusive. Use anything else.

Someone even recommended the Visitor pattern. Use this when you have an object which follows the Composite design pattern. This depends on polymorphism to work, so it's not really a different solution.

like image 123
S.Lott Avatar answered Oct 23 '22 14:10

S.Lott