How to Write a Python Switch Statement

I’ll admit, I don’t use switch statements very often when programming. When I do, it has always been in Javascript. So when I found myself wanting to use a Python switch statement recently, I discovered that the switch/case statement doesn’t exist in the language.

The Python Switch in a Nutshell

If you don’t want to read a long article, here are the basics on how to implement a switch statement in Python. You simply need to create a Python Dictionary (otherwise referred to as an associative array) where the key is your case choice and the value is what gets returned. Then call the dictionary get() method to return the value based on the case.

Here’s what the Pythonic switch-like statement looks like:

def switch(arg):
switchy_thing = {
"case 1": "something",
"case 2": "something else",
"case 3": "something big",
"case 4": "something bigger" ,
"case 5": "something huge!!",
"case 6": "Some really ginormous thing!!!"
}
return switchy_thing.get(arg, "Nothing")

print switch("case 4") #prints "something bigger"

Let’s take a closer look at what’s happening here. Inside the switch function, Switchy_thing is a dictionary containing six “case” statements. These are actually just key/value pairs. After the dictionary is defined, we call the built-in get() method in order to get the value we want out of the dictionary.

The get() method takes in two parameters. The first parameter is the name of the key with the value you are trying to have returned. The second parameter is the default value that get() will return if the key you passed doesn’t exist. This is analogous to the default statement inside of the switch statements of some languages. If our example above called switchy_thing.get(“case 10”, “Nothing”) , it would return “Nothing” since there is no key called “case_10.

dictionary.get(key[, value]) 

As an alternative to using dictionary.get(), you can retrieve a key’s value using square bracket notation with the dictionary name. In our example, to get “case 6” we would write switchy_thing[“case 6”] which would return “Some really ginormous thing!!!”. The problem with doing it this way is there’s no default value failover. If you call switchy_thing[“case 10”] you will get an error.

Here’s how an actual switch statement works in JavaScript:

let someVariable = 5;

switch(someVariable){
case 1:
Some code block...;
break;
case 2:
Some code block...;
break;
case 3:
Some code block...;
break;
case 4:
Some code block...;
break;
case 5:
console.log("case 5 was selected");
break;
case 6:
Some code block...;
break;
default:
"A bad value was entered";
}

//logs "case 5 was selected"

If you’re a JavaScript developer like me, you’ll recognize the code example above. There are several similarities between the JavaScript switch and our Python implementation. First, both look like key value pair constructs.

Both are wrapped in curly braces and separate the cases/keys from the return value with a semi colon. Both have a default value (if you use the get method with the Python implementation).

There are also some differences. The JavaScript default is contained in the body of the switch statement while we’re sort of hacking it in there with Python’s get(). Also, you’ll notice that there’s a break statement in each of the JavaScript case statements that are not present in our Python code. JavaScript doesn’t just jump out of the switch statement when a case is found true. Without the break keyword, control of the switch statement will simply fall through to the next case. It will keep doing this until it hits a break or gets to the default. For example, you could write this in JavaScript:

function pennyWise(year){
switch(year){
case "1858":
console.log("flying eagle cent");
break;
case "1877":
console.log("indian head cent");
break;
case "1910":
case "1934":
case "1977":
case "present":
console.log("Lincoln penny");
break;
default:
"A bad value was entered";
}

pennyWise("1877"); //logs "indian head cent"
pennyWise("1934"); //logs "Lincoln penny"
pennyWise("present"); //logs "Lincoln penny"

We don’t need a break statement in our Python switch because by its nature it only allows a single decision to be made. This is a good thing unless for some reason you rely on this kind of multiple-case behavior.

Come to think of it you can sort of implement the above multiple-case behavior in Python but with an, if statement and the keyword or. You could write:

def switch(val):
if val == 0:
print "you printed zero"
elif val == 1 or val == 2 or val ==3 or val == 4:
print "you printed something between 1 and 4"
else:
print "You don't know how to count"

When do you want to use a switch-like statement in Python?

The case (this pun was stumbled upon and intentionally left in) for using a dictionary/switch statement rather than an if-else is really all about clean looking code and having to write less of it. There might be an argument where one or the other performs better with huge data sets but most of us won’t have to deal with data of that magnitude.

If you do happen to be a big data junkie, all I’ll say is that … it probably still doesn’t matter. It’s not worth worrying about unless your code is slowing to a crawl. Even then it might not be your branching logic that’s at fault. In situations like this, you’ll want to profile your code and try to figure out exactly where the blockage is.

So basically, you’ll use the switch-like statement whenever you feel like it. A good rule of thumb is to use it when you have more than ten if-elif blocks. Even then, it’s just for human readability optimization rather than computer performance optimization.

Why is there no switch statement in Python?

My use case that prompted this post wasn’t that exciting or important. I probably could have just used a slightly larger than usual if/elif statement to do the work. But I hate not knowing how to do something or why something is missing. So I set out to research the mysteriously missing Python switch.

Turns out, it’s not that mysterious after all. Guido van Rossum and the Python team have never put it in the language. They didn’t think it was necessary. In fact, in the official documentation, there’s really no reason given. It basically tells the reader to deal with it and use if/elif/else statements where you just keep adding elifs for each case you want to include.

The docs go on to say that if you have a lot of cases to choose from you can set up a dictionary mapping to emulate a switch. Oh, hey, that’s what were doing in this article!

None of this is to say that no one wants a switch-case statement in Python. There have been a couple of proposals put before the Python team with solutions to a supposed problem. But each time switch comes up it gets rejected. It’s unlikely to ever become a part of the language.

Conclusion

While Python doesn’t have a native switch implementation, it’s fairly easy to emulate the functionality using dictionaries and its built-in get() method. Or, instead of trying to patch together a switch, you can just use if – elif – elif … until you’ve listed all of your cases. Then you can use the else clause as your default value. There’s really no performance advantage to either one for most programmers. But once you get more than, say, 10 elifs, your code can start to look a little messy. At that point, you might consider the dictionary/switch syntax. Beyond that it doesn’t really matter.

Toggle Layer Visibility Using URL Parameters in Web App Builder Developer Edition

ESRI’s developer edition of their Web App Builder (WAB) is a handy stand-alone tool for creating web mapping apps. While the WAB is a tool for building an app without needing to code anything, the developer edition allows users to create their own widgets and extend current functionality or themes. Even with this capability, however, there are some situations where the pre-formed development framework just doesn’t go far enough.

This was the situation I found myself in recently when trying to use the WAB to replace our custom built web map viewer at work. Our current viewer interfaces with a few third-party apps by accepting URL parameters that turn on or off layers and query various layers. The WAB does allow for querying layers using URL parameters but it doesn’t have the ability to toggle layers using the URL method.

I searched around the internet trying to find someone who has solved this problem but never found a useable solution. ESRI provides URL parameter layer visibility functionality on their ArcGIS Online platform but this hasn’t made it to the WAB Developer Edition yet. I’m not sure when or if it will.

Since layer toggling is a must-have functionality for us I decided to work up a solution myself. Thankfully, the developers at ESRI named the WAB’s URL handling module mapUrlParamsHandler.js so it was pretty easy to figure out what needed to be modified.

Parameter Modeling

To fix my problem I just had to add one new function. The actual turning on and off of the layers in this function was taken care of by the WAB API. The biggest concern for me was deciding on how the parameters should be passed in the URL so they would be easy to use on the client side and easy (and fast) to process on the server.

I considered using the Esri ArcGIS Online model of ?layers=show:0,1,2,3 for passing in layer visibility parameters. However, this becomes very cumbersome when considering showing and hiding both layers and sublayers. It would look something like ?layers=show:0,1.0-2-5,3,4;hide:6,7 or some other cryptic looking mash of numbers and characters. I wasn’t even sure the online API accepted a hidden parameter. They don’t show one in their documentation.

I then considered using two separate parameters for showing and hiding (?showLayers=1,2,3&hideLayers=1,2,3) but this just adds more complexity to the code on the back side as well as the parameters the client has to plug in. Ultimately I settled on using a single parameter called layers. But then I needed to decide how to reference those layers.

If I used a zero-based index URL parameter list, then if the layers in the web map ever change position, I’ll have to go in and change the URL references to those layers. On the other hand, if I used the titles of the layers, it wouldn’t matter what the index position of the layer is. The name of the layer and the title would still be the same.

It’s true that the title of the layer could change too. In that case, we’d still have to update the URLs we’re passing into the app. But in our situation, this is less likely to happen than the position changing. Using titles has another advantage of making it clear to the casual observer exactly what layers are being acted upon. This wouldn’t matter that much since the public isn’t going to be encouraged to pass parameters into the URL. But it might be nice for us developers to know what we’re doing.

I ended up using layer titles since they’re human readable and don’t rely on positioning within the web map that drives the web app. However, I created both versions of my modifications so that someone else who wants to use layer indices can do so just as easily.

In my parameter, layers are separated by commas with layers to be shown represented by the layer title (or positive index integers) and layers to be hidden represented by layer titles with a minus(-) symbol in front of them (or negative index integers).

Toggling Sub Layers

I also wanted to be able to toggle sub-layers on and off. Sublayers to be toggled will be shown by separating the parent layer from the sublayers with a colon. The sublayers themselves will be separated by semicolons.

In WAB apps, sublayers are 0 indexed underneath their parent. Suppose you have an active layer called School Boundaries with a map index position of 6 and it has three sublayers for High Schools, Middle Schools, and Elementary Schools. These sub-layers would be indexed as 0, 1, 2.

I decided to stick with index references for the sublayers since it was easy to do so and makes sense. It’s also easier to read in and understand within the URL since the parent layer is text so there’s some contrast. 

With the above model of building your URL for layer toggling, you can take care of almost any layer manipulation scenario you can think of.

This would turn on the Schools layer as well as the first, second and third sublayers: 
?layers=Schools:0;1;2

This would turn off the Schools layer and deselect sublayer 0, then turn the schools back on and select sub layers five and six:
?layers=-Schools:0,Schools:5;6

Edit: Having to turn an entire layer off and then on again, just to get at the sublayer, was cumbersome. Now you can use the minus symbol in front of the layer title or the sublayer index to turn them on and off independently. For example – ?layers=Schools:-0;5;6


Multiple Params


Another problem I have with the URL parameter handling capabilities of the Web App Builder is that you can’t add multiple parameters. In other words, you can’t pass in layers to turn on and do a query on a layer at the same time. To solve that problem I just modified the main function in the module to check all URL parameters rather than stopping after finding the first one.

mo.postProcessUrlParams = function(urlParams, map){
    //urlParams have been decoded.
    for(var key in urlParams){
      //Loop through the urlParams object
        if(urlParams.hasOwnProperty(key)){
          //For each parameter found, run its function
          if('layers' === key){
            toggleLayers(urlParams, map);
          }else if('extent' === key){
            setExtent(urlParams, map);
          }else if('center' === key){
            setCenter(urlParams, map);
          }else if('marker' === key){
            createMarker(urlParams, map);
          }else if('find' === key){
            sendMessageToSearch(urlParams);
          }else if('query' === key){
            queryFeature(urlParams, map);
          }
        }
    }
  };

How to Use

In order to use the modified mapUrlParamsHandler module in your WAB project, you first need to download the appropriate one (index driven or title driven) from Github at https://github.com/RyanDavison/WAB_URL_Parameters. Then replace the native file located in \WebAppBuilderForArcGIS\server\apps\<Your Apps ID Number>\jimu.js .

If you’ve already exported your app and are hosting it on your own server just find the jimu.js folder and paste the file in there. Alternatively, you could just copy the code out of the files on Github and paste it right into the native mapUlrParamsHandler.js file. That’s all you have to do to get layer toggling functionality through your URL.

In the future, ESRI might enable this same functionality in the WAB Developer Edition. If they do, it’s a good bet they won’t have the same URL structure as me. As I’m writing this, The Web App Builder is at version 2.9. So if you start using my modified code now, you might be changing your own URL structures to match the ESRI API in the future.

If you have any questions, comments or problems feel free to leave them in the comments section below or contact me on Github.

EDIT:
When I first wrote the modification You could only turn sub-layers on and off along with their parent layer. So, if you wanted to turn off sub layer 2  but turn on sub layer 3 of LayerX you would have to write

?layers=-LayerX:2,LayerX:3

It was a two-step process that was very clunky. Now, you can turn off sublayers independently. So the query above would now simply read:

?layers=LayerX:-2;3

Of course you can still turn off an entire layer like this:

?layers=-LayerX

Create Files Without Extensions in Windows

If you use Git for anything you’ve probably had occasion to create a .gitignore file. The gitignore file simply tells Git to ignore specified files or directories that you don’t want managed by version control.

But if you’re a Windows user it can appear difficult to create the file. That’s because the file explorer doesn’t let you create files without an extension. A typical work around is to open a command window and use the rename function to rename a .txt file to a file without an extension. This works but it’s a pain. The easier solution is simply to create a text file with the file explorer but name it .gitignore. .

Putting the dot on the end of the file name without a declared extension results in the desired extensionless .gitignore . Of course this will work for any other extensionless file you want to create.

Other People’s Code

I like looking at other people’s code. Said in the right voice, that could sound quite creepy. But I like to see what kind of projects they’re working on, how they implement solutions, what languages they chose to work with and how many other people are using their work. So I’ll keep looking at other people’s code. At night. Through their window. While they work.

Sometimes, I’ll just go to GitHub and search for a language or maybe a keyword having to do with something I’m doing in one of my own projects. This usually gives me a couple of hundred pages of repositories to look through. I’ll click on page 99 or 100 of the results just to “randomize” what I’m seeing a little.

Over the last couple of weeks, I started realizing that I was only searching for code in languages that I was familiar with. Within those languages, I was only really reading code that I already understood or was familiar with. That didn’t sit right with me because I wasn’t seeing anything new or interesting.  I felt like I wasn’t growing as a developer. I was staying comfortable and not challenging my skills.

So I decided to do something about it. I wrote a short little Python script (and later created a more convenient JavaScript bookmarklet) that randomly selects a repository and opens it. Ok, Ok, it’s not that exciting or inspiring. Nor is it original or even useful. It has a bug or two and should probably be developed a little more to give the user more options to filter things out.

But the idea was to gain exposure to new coding styles, languages, and technologies and on those points, it is a success! I have started a weekly habit of searching randomly using the bookmarklet and whatever result I get, I force myself to read through it and try to understand it. If I think the code is interesting enough I will try to implement it locally.

If you’re interested, you can find the repository at https://github.com/RyanDavison/RandomRepo . Feel free to fix bugs, add features or anything else. If you just want to play around with finding random repositories you can drag the link on this page to your bookmarks bar and click away.

It’s Always Been Broken

Sometimes, when debugging an error that has just popped up in a program, the problem lies in some external parameter that has recently changed. Most of the time, however, the thing that has changed only serves to reveal how some static code had a dormant bug already. The code can work under one set of parameters but not another. Either way, it has always been broken.

It’s The Little Things That Get You

I spent some time today dealing with a layer of data that was added to an ESRI REST service. The service layers are zero base indexed which means you can reference them based on their position relative to each other. The first layer is identified at position zero while the second is 1, the third is 2 and so on.

The new layer was just before the fourth existing layer. This means the new layer became the fourth, the fourth became the fifth and the fifth became the sixth. Are you following along?

 

Anyway, I was working on a web app that consumes this service and it references the service layers based on those index positions. I added some new markup and some code for the added layer and changed the existing code to reference their two new position numbers. At first everything seemed to be working fine. Then a coworker noticed that the new layer’s data was showing on screen by default (you’re supposed to check a box first). It took me a while before I finally realized that it was being controlled by a different checkbox that controls the layer right after it in the service.

To make an already long and confusing story shorter, there was a second reference to the service indexes in my code. When I had designed the app a few years ago I, for some reason, found it expedient to make two, hard coded references to the index. Instead of taking the time to create a variable, I had repeated a hard coded number that could be changed by an outside source.

My poor design choice came back to bite me. Not only did I repeat code, I made it confusing to update. It’s embarrassing to admit that I wrote code that even I couldn’t figure out later. But it goes to show that taking the time to design things correctly from the start will pay off in the future. It’s the little things that get you; that second hard coded index number that’s nearly impossible to notice.

Future Proofing a Technology Career

Is it possible to “future proof” a career in technology?  An article yesterday by IDG Connect proposes that to future proof your technology career you should learn “cyber security, business intelligence, data science/big data, DevOps, JavaScript and UX/UI development and design”.

Their suggestions are based on the fact that these domains are in high demand right now. But the must have technology today may be the forgotten technology of tomorrow. Basing your career on a single language or specialty almost ensures your skill set will become obsolete.

Specializing in a given tech field or becoming proficient in a particular programming language isn’t bad. But you shouldn’t base your entire career on it. A better approach is to gain broad knowledge in computer technology or programming and supplement that with specific expertise. That way when the language of the day changes or the cyber security field is saturated with employees, you’ll be able to shift to the new tech need easier and with more authority.

But there might be an even better way to avoid technology skills obscurity. In his book You Can Do Anything, author George Anders suggest that the key to securing a long lasting place in the work world is to develop skills that might be completely unrelated to what you think you should learn. The book’s premise is that a liberal arts degree could be the key to securing high paying jobs in a number of career fields including technology.

Anyone can learn a programming language. Anders says it’s “nothing that can’t be picked up in a few months of concentrated effort”. But it takes a different skill set to think creatively and apply technology training to the problems companies face. Liberal arts degrees can give you those different skill sets.

They can help you develop creative and critical thinking, communication and obtuse analysis skills among other things. My own political science degree solidified my analytical abilities and taught me how to look beyond seemingly obvious answers to problems and find solutions with more permanent outcomes. And it was my interest in political theory and intelligence that led me to a career in geographic information systems.

Having a computer science degree doesn’t doom you. Science degrees still produce some of the primary skills tech employers are looking for. But if you want to guarantee your place in today’s ever changing world of technology, hone your soft skills. Carve your own niche by looking outside of technology for the skills businesses are looking for in their best employees.

Objective Reasoning – The Basic Javascript Object

What is an Object?

In Javascript an object is simply a container or store of properties that are related to what the object is modeling. These properties can be primitive data types, other objects or functions. Here’s an example of an empty object with no properties:

const furBearingTrout = {};

I’ve used object literal notation which is doing just what it sounds like – literally writing out the notation of an object. We do this using curly braces {}.

How to create properties

When we want to set a property on our object we can do it one of two ways:
1. Use bracket notation where we state the object name along with a property name in brackets and then assign a value using the equal sign:

furBearingTrout[“name”] = ‘Alpino-Pelted’;
furBearingTrout[“url”] = 'http://www.furbearingtrout.com/fish2.html';

2. Use dot notation where we state the object name followed by a dot followed by the property name we want to use and then assign a value using the equal sign:

furBearingTrout.name = ‘Alpino-Pelted’;
furBearingTrout.url= 'http://www.furbearingtrout.com/fish2.html';

I could have created our object with properties already assigned. Note that properties are written as name:value pairs separated by commas.

const furBearingTrout = { 
  name: ‘Alpino-Pelted’, 
  url: 'http://www.furbearingtrout.com/fish2.html'
}

How to access properties

Once we have properties we can access them using the same two methods we used to set them just without the equal signs that assign values.

console.log(furBearingTrout.name); //outputs ‘Alpino-Pelted’
console.log(furBearingTrout[‘url’]); //outputs 'http://www.furbearingtrout.com/fish2.html'

We can also create objects using the constructor method (new Object) or the Object.create() method but for this article we’ll stick to the literal notation for its simplicity and visual aid.

Functions in objects are methods

When the property is a function we call it a method. Methods do something with the data stored in the object. Imagine we had the following properties:

const furBearingTrout = {
  name: ‘Alpino-Pelted’,
  url: 'http://www.furbearingtrout.com/fish2.html',
  view: function () {
    console.log(`View the ${this.name} trout at ${this.url`;)
    }
}

You call a method by accessing the property name it’s associated with followed by parentheses.

furBearingTrout.view(); //ouputs ‘View the Alpino-Pelted trout at http://www.furbearingtrout.com/fish2.html

Why do I use ‘this’ ?

The ‘this’ keyword simply references the very object it’s inside of. So this.name is the same as saying neighbor.name. Outside of the object we would refer to furBearingTrout.name but inside the object we refer to this.name.

There’s a lot more to objects than what I’ve written here. But if you understand these basics you’ll already be able to model some fairly complex real world data and be able to manipulate it.

The Integrated Developer’s Environment

I was home sick from work the other day and had plenty of time to think. It occured to me that whenever I go in to the office I am very productive almost immediately. When I’m home, I tend to have little enthusiasm for programming. When I attempt to program at home I’m usually nowhere near as productive as at the office.

It hasn’t always been that way. When I lived in Las Vegas I wrote code at home on a regular basis. My immediate thought was that I don’t currently have the right hardware to be productive at home. In Las Vegas I had a decent desktop PC with two monitors and a hardwired internet connection. I currently have an old, slow laptop that shares a wireless connection among several people and lots of devices.

But is it really the hardware that holds me back? Most of my work is done in JavaScript which can be written with lightweight text editors/IDEs (I use Atom these days). I don’t need a lot of computing power for that. Honestly, my high-end rig at work is mostly for large imagery datasets and working with GIS.

I started realizing that it’s less the hardware and software that impacts my productivity and more the intended use of those things. When I go to the office, I use that computer for work. My home computer is used for surfing the web, writing emails and watching Netflix. When I sit down at it, my brain switches to mindless mode. I find myself wandering, checking email or googling things that pop into my mind.

So it’s less the development environment and more the developer’s environment that inluences his productivity. In my Las Vegas home I had set up my computer in a separate room and only really used it for programming. We had a separate laptop (the same one I have now) for web surfing and intertainment. For me, I have to have a psychological, if not physical, separation between work (anything that takes concentration and thought) and play. I would like to spend some time working on some open source projects on the weekends so it looks like I’m going to have to carve out some space in the house or a dedicated office.

Chrome Developer Tools

As a JavaScript developer I need tools that help me figure out what’s going on between my code and the browser. Thankfully, most major browsers today provide developer tools that do just that.
Google Chrome toolbox.
With these tools you can see exactly how your code affects the browser. At runtime you can find errors in code you’ve written or how long your site takes to load. You can view or even rewrite your CSS rules to see what changes will look like before you ever even commit them to your source files.
You can also dig into the browser itself and inspect its cookies, local storage and cache. And with web users quickly transitioning to mobile devices, developer tool device emulation can show what your site looks like on, and how it will interact with, phones and tablets.
Every year that passes gives us better developer tools from the major browser makers. We are fast coming to a point where any tool you choose will be just as good as another. But for one reason or another developers tend to find themselves gravitating towards a particular set of tools.
When I surf the web I like to use more privacy oriented browsers like, well, anything but Google’s Chrome. But when it comes to debugging and developing code, Chrome takes first place in my world. I like the default look of the Chrome tools UI (although Mozilla’s Dark theme is slightly more pleasant to look at if you’re into dark themes). I also find Firefox developer tools to be a little slow when emulating mobile devices while Chrome is snappier. Other tools in Chrome also appear more polished and have more functionality.

Some browser developer tools might have features that others don’t but that’s usually only true until the others release their next version. Good ideas tend to spread themselves around quickly.
There are lots of tools out there for JavaScript developers and web designers. But Chrome’s developer tools provide great runtime debugging, design assistance and performance insights. If you’re a web developer and are not using these tools and features to the fullest, it’s worth taking the time to dive deep.