Python vs. Java

One of the major reasons my company prefers Java over Python, is Java’s static type declarations (and all the benefits that follow). If only Python had that, my life would be so much nicer. Here is an example of code I have to work with, and an example of what the Python equivalent would look like.

The background of the code: We have a list of “identifiers” that can identify people who want to use a parking garage. These can be NFC cards, credit cards, and bar codes. We want to filter the list of known identifiers and return only those of type “barcode”.

The code in Java:

private List<Identifier> barcodeTypeOnly(List<Identifier> ids)
{
    final List<Identifier> barcodes = new ArrayList<Identifier>();

    for (Identifier id : ids) {
        if (id.getType().equals(Identifier.TYPEBARCODE)) {
            barcodes.add(id);
        }
    }

    return barcodes;
}

What it would look like in Python:

ids = the list of identifiers

barcodes = [identifier for identifier in ids
            if identifier.type == Identifier.TYPEBARCODE]</pre>

You could write that last one on a single line, but for clarity I wrote it like this. I understand that the list comprehension construction may not be instantly recognisable, so I wrote a little explanation after the break.


A primer on list comprehensions

The idea behind list comprehensions is that an iterable (like a list) goes in, and a list comes out. In its simplest form:

result = [someobject for someobject in somelist]

This would give you a shallow copy of the list, so it’s a silly example. Here is a more useful one - let’s say all your objects have a name, and you want to create a list of names:

names = [someobject.name for someobject in somelist]

In Java it would be coded like this:

private List<String> getNames(List<NamedObject> objects) {
    List<String> names = new ArrayList<String>(objects.size());

    foreach(NamedObject object : objects) {
        names.add(object.name);
    }

    return names;
}

Adding a filter

Let’s say you don’t want a list of all object names, but those names where someobject.type == 'car'. That’s where the if clause comes in:

names = [vehicle.name
         for vehicle in somelist
         if vehicle.type == 'car']

Filtering can be very useful; I’ve used this in a testing environment, where commands are executed and can fail or succeed. Getting a list of all failed commands is as easy as:

failed = [command for command in executed
          if command.status != command.SUCCESS]

Other similar constructions

You can create a “generator expression” by using the same syntax, but removing the blocky brackets. This allows you to efficiently use the any() or all() functions, for example:

success = all(command.status == command.SUCCESS for command in executed)

This will stop iterating the executed list as soon as a single failed command was found.

Recent versions of Python (3.1, 2.7) have other, very similar constructions. With the same ease you can create and filter sets and dictionaries.

dr. Sybren A. Stüvel
dr. Sybren A. Stüvel
Open Source software developer, photographer, drummer

Related