Switching to Python
Thomas J. Kennedy
1 Data Structures
When I work in Python, I generally focus on three core (fundamental) data structures.
- Lists:
prime_numbers = [1, 2, 3, 5, 7, 11, 13, 17, 19]
- Dictionaries:
favourite_colors = {"Thomas": "Blue", "Jessica": "Purple"}
collections.defaultdict
collections.Counter
- Sets:
some_colors = {"Blue", "Red", "Green", "Cyan", "Teal"}
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++ Loopusing 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 Loopdef 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 Loopdef 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 Loopdef 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 Streamsimport 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:
- There is less boilerplate code.
- It is impossible to forget to close/deallocate a resource.
To write to a file, one might write:
Example 7: Python File IO - Basictext_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.