4 ms·
Speaking of coding niceties, when I started branching out from bash into a 'real' language, Python, I couldn't find a switch statement. A colleague of mine said
by vacri 10y ago
Speaking of coding niceties, when I started branching out from bash into a 'real' language, Python, I couldn't find a switch statement. A colleague of mine said that Python didn't have one, and that switch statements were a 'code smell'. I didn't really understand that, and asked about those times that you genuinely could use a switch statement, and the answer was "just use a long if-else function". I can't remember his justifaction for it, so clearly it didn't stick
I still don't see the real pragmatic difference between a switch statement and a long if-else function - anyone feel like ELI5'ing it for me? Switch statements just seem more concise and readable to me...
- somestag 10y agoIf your switch is more than a few lines, the Pythonic way is to use a dictionary, rather than many if-else statements. A dict is roughly as concise as a switch, and it's also much easier to work with and extend. Following the principle of "There should be one--and preferably only one--obvious way to do it," switches in Python are redundant. If you want branching logic, then use branching statements (if-else). If you want mapping, use a dict. The hiccup is that many programmers new to Python don't actually know what a dictionary is--or at least haven't used one before--so it's far from "obvious" to them to use it.
- gknoy 10y agoSwitch statements have fall-through behavior that you need `break` to avoid (in most languages); sometimes this is what you want, but only rarely. One trick I've seen people do in Python is to use a dict; define lambdas for each case, and then key the dict on your value that you would switch on, and invoke the lambda (or use existing functions). def fake_switch(self, thing): { 'foo': self.do_foo, 'bar': self.do_bar, 'frog': self.blast_vent_core }[ thing ]() I am doing a poor job of explaining _why_ one might want to do that, but one advantage is that you can verify that the right callbacks were called in tests, and also verify that each callback behaves right when invoked, since they are just references to methods or functions. I'm not sure if doing this would get marks for cleverness and testability, or would get one criticized for excessive cleverness. As the reviewer of the code when a coworker wrote it, I recall liking it, though.
- optionalparens 10y agoThere are multiple alternatives to switch (or if) statements and I would generally agree switch statements are mostly a code smell. As one posters described, using the fall-through behavior is more what justifies it and the real difference. I know you asked for ELI5, but let me give you some options to think about how you code on a broader level and how to eliminate both if and switch or at least improve them. If you think of a switch statement as a pattern matching construct, then you will realize there are many, many alternatives in any programming language, including Python. For instance, the dict method works, as can anything that operates a collection-oriented data structure. For example, you could just as easily loop on a list and do this too, but for most lists this would require a worst case of O(n) iterations where n is the size of the list to match, thus a dict is better. A dict would not work if you want fall-through since you would only be matching on a single key usually, unless once again you do lookups of multiple keys (dict still wins). But a list would support this fall-through behavior with minimum effort and a small list would preform alright. If your usage is lets say more sophisticated than a key lookup, there may be alternative data structures that you can use to achieve similar results (b-tree, red-black tree, skip list, etc.) though that is of course getting further from the usual behaviors of switch statements. A functional way to go about it would be to reduce or fold on some collection. If you think about the items that don't match, they wouldn't add anything into the final reduction much in the way map/reduce works traditionally. Many times this would just consolidate the entirety of the function you are calling the switch with the result it is producing. Generally, I'd encourage thinking of writing code that operates on data and thus tends to make good reduce of things like reduce, map, filter, etc. as this often simplifies things and in some cases can actually lead to nice performance if done right. It also tends to force you to write things atomically, with less side-effects, and as pure functions. One of the problems people have with if-statements is they end up burying unrelated concerns or bug-inducing side-effects in each if/else or each branch. This code smell is easy to detect by simply pretending you are looking at new functions for each piece of code under an if/else or case and seeing if they are returning the same "type" in general sense of thing, how much there is in common between each piece, and if they are doing 1 or multiple things each. Most of the time, you are really doing the same thing with one slight difference like an input parameter, and you never really needed an if or at the very least, it could be handled differently. If you are doing more than one thing per if, it often means you are doing too much. Furthermore, you should test that if you were to repeatedly pass the same data to each, would you get the same result? Another way of handling this is to use multi-methods. Note that in truth, it's the same as above because all you are doing depending on your implementation is pattern-matching. It just depends if your behavior is match one or match multiple (fall-through-like). Python can use attributes to do multi-methods among a few other ways. It's been awhile and mostly I'd avoid using them for performance reasons, but it's another option when thinking of more advanced ways to get rid of switch or if constructs. In general, it's worth noting that in many languages such as Python, though ifs/switch might be ugly, they can often perform pretty well. It is also worth knowing that if/switch are not very good for functional styles sometimes. Making lists or dicts or other constructs is not always free, or slower/faster so it can sometimes just be a balance between performance, clarity, and composition. Hopefully that gets you thinking and is not too confusing. A bit exhausted so I'm not thinking my best, though I think I am sending you down a track to explore to help you grow.