Switching to Python

Thomas J. Kennedy

Contents:

1 Data Structures

When I work in Python, I generally focus on three core (fundamental) data structures.

If we want to map these to (modern) C++ and Java… we end up with…

Python C++ Java
list std::list java.util.List
dict std::unordered_map java.util.HashMap
set std::unordered_set java.util.HashSet

1.1 Lists & List Comprehensions

The next few discussions will include list comprehensions, dictionary comprehensions and set comprehensions.

Suppose we have a list of programming terms and want to create a second list containing the length of each term. We might take the usual C, C++, or Java approach:

Example 1: Word Count - Boring C++ Loop
using std::string;
using std::vector;


int main(int argc, char** argv)
{
    vector<string> some_terms {"Hello", "world", "with", "for", "while", "int"};
    vector<int> term_lengths(some_terms.size(), 0);

    for (int i = 0; i < term_lengths.size(); i++) {
        term_lengths[i] = some_terms[i].size();
    }

    return 0;
}

and translate it into Python:

Example 2: Word Count - Boring Python Loop
def main():
    some_terms = ["Hello", "world", "with", "for", "while", "int"]

    term_lengths = []

    for term in some_terms:
        term_lengths.append(len(term))


if __name__ == "__main__":
    main()

The Python version can (and should) use a list comprehension.

Example 3: Word Count - Fun Python Loop
def main():
    some_terms = ["Hello", "world", "with", "for", "while", "int"]

    term_lengths = [len(term) for term in some_terms]


if __name__ == "__main__":
    main()

Depending on how many terms we have… a generator expression might be more appropriate:

Example 4: Word Count - Really Fun Python Loop
def main():
    some_terms = ["Hello", "world", "with", "for", "while", "int"]

    term_lengths = (len(term) for term in some_terms)


if __name__ == "__main__":
    main()

1.2 Modern C++ and std::transform

Modern C++11 and newer provide the std::transform method. Combined with lambda functions we can take the original C++ code… and rewrite it as

Example 5: Word Count - C++ `std::transform`
using std::string;
using std::vector;


int main(int argc, char** argv)
{
    vector<string> some_terms {"Hello", "world", "with", "for", "while", "int"};
    vector<int> term_lengths;

    std::transform(some_terms.begin(), some_terms.end(), std::back_inserter(term_lengths),
                   [](const string& t) -> int {
                       return t.size();
                   });

    return 0;
}

Java has the java.util.stream package, which provides similar functionality to Python comprehensions and C++ std::transform. However, in Java, we would end up dealing with the Integer wrapper class if we wanted to use a non-array data structure.

Example 6: Word Count - Java Streams
import java.util.Arrays;
import java.util.List;

public class IntStreamDemo
{
    public static void main(String... args)
    {
        List<String> some_terms = Arrays.asList("Hello", "world", "with",
                                                "for", "while", "int");

        int[] term_lengths = some_terms.stream()
                           .mapToInt(s -> s.length())
                           .toArray();
    }
}

The Python implementation is the most succinct, approachable, and readable.

2 Context Managers

Python provides the with statement (construct). This allows the setup and teardown involved in using resources (e.g., files, sockets, and database connections) to handled elsewhere.

This has two main benefits:

  1. There is less boilerplate code.
  2. It is impossible to forget to close/deallocate a resource.

To write to a file, one might write:

Example 7: Python File IO - Basic
text_file = open("some_file.txt", "w")

for number in range(1, 100):
    text_file.write(f"{number}\n")

Did you notice the missing fclose(text_file)? With one small with the file close operation will be handled automatically.

Example 8: Python File IO - Using `with`
with open("some_file.txt", "w") as text_file:
    for number in range(1, 100):
        text_file.write(f"{number}\n")

This also works for other types of files–including compressed files.

Example 9: Python File IO - Using `with` and `gzip`
import gzip

with gzip.open("some_file.txt.gz", "wt") as text_file:
    for number in range(1, 100):
        text_file.write(f"{number}\n")

3 Python Includes Batteries

For many languages external libraries are usually required for common operations. Python includes batteries.

Operation Built-in Python Module
Zip Files import zipfile
GZipped Files import gzip
Reading, writing, or generating JSON import json
Converting objects to JSON import json
Serializing objects and data structures import pickle
Working with time import time
Working with dates and time import datetime
Working with SQLite import sqlite3
Building a calendar import calendar
Generating log files import logfile
Advanced command line arguments import argparse
 

When external libraries are required, the Python pip utility and a requirements.txt can be used for all dependency and configuration management.

In C/C++ we hope for a Linux environment (or Docker). In Java… Gradle is a popular build and configuration management tool.