I am going to go for a Raymond Hettinger style presentation, https://www.cs.odu.edu/~tkennedy/cs330/f20/Public/languageResources/#python-programming-videos.
These materials are web-centric (i.e., do not need to be printed and are available at https://www.cs.odu.edu/~tkennedy/python-workshop).
Who am I?
I have taught various courses, including:
- CS 300T - Computers in Society
- CS 333 - Programming and Problem Solving
- CS 330 - Object Oriented Programming and Design
- CS 350 - Introduction to Software Engineering
- CS 410 - Professional Workforce Development I
- CS 411W - Professional Workforce Development II
- CS 417 - Computational Methods & Software
Most of my free time is spent writing Python 3 and Rust code, tweaking my Vim configuration, or learning a new (programming) language. My current language of interest is Rust (at the time of writing).
Referenced Courses & Materials
I am going to pull from CS 330, CS 350, CS 411W, and CS 417 lecture notes
- CS 330 - Object Oriented Programming & Design
- CS 350 - Introduction to Software Engineering
- CS 411W - Professional Workforce Development II
- CS 417 - Computational Methods & Software
I will also pull a couple examples from my previous Git workshop, https://www.cs.odu.edu/~tkennedy/git-workshop.
The Broad Strokes
T.B.W
Best Practices
- Design Paradigms
- S.O.L.I.D
- Iterators - (CS 330)
- Modern Language Constructs
Tools of the Trade
- Vim (the only editor anyone ever needs)
- Configuration Management
- External Libraries
- Cross-compilation
- Continuous Integration & Deployment
- Documentation
- Javadoc
- Pydoc
- Doxygen
- Rustdoc
- Code Style
- Static Code Analysis
- Code Linters
- Style Checkers
Testing & Development
- Test Driven Development
- Unit Testing & Integration Testing
- Hamcrest Matchers
Topics
- A quick overview of procedural, object-oriented and functional style programming (very briefly).
- PEP 8, https://www.python.org/dev/peps/pep-0008/ and PEP 20, https://www.python.org/dev/peps/pep-0020/
- Loops, context managers, and list/generator comprehensions, https://www.cs.odu.edu/~tkennedy/cs330/f20/Public/switchingToPython/index.html.
The basic Python data structures (List, Dictionary, and Set)- Generator Expressions
- A few Python modules, including Zip, json, and argparse, https://www.cs.odu.edu/~tkennedy/cs330/f20/Public/switchingToPython/index.html#python-includes-batteries
- Writing Pythonic code (e.g., using enumerate), https://www.cs.odu.edu/~tkennedy/cs330/f20/Public/whichLanguageIsIt/index.html#a-little-python.
- Time permitting... a little unit testing.
Procedural, Object-Oriented & Functional Programming
There are generally three styles of code found in Python:
Procedural
point1 = (0, 5)
point2 = (8, 3)
point3 = (1, 7)
points = [point1, point2, point3]
for point in points:
print(sqrt(point.x ** 2 + point.y ** 2))
Object Oriented
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self):
pass
def __hash__(self):
pass
def __str__(self):
pass
Functional
point1 = (0, 5)
point2 = (8, 3)
point3 = (1, 7)
points = [point1, point2, point3]
shortest_distance = min((sqrt(point.x ** 2 + point.y ** 2)) for point in points)
largest_distance = max((sqrt(point.x ** 2 + point.y ** 2)) for point in points)
average_distance = sum((sqrt(point.x ** 2 + point.y ** 2)) for point in points) / len(points)
Of course... we should clean it up...
points = [(0, 5), (8, 3), (1, 7)]
distances = [sqrt(point.x ** 2 + point.y ** 2) for point in points]
shortest_distance = min(distances)
largest_distance = max(distances)
average_distance = sum(distances) / len(points)
None of these examples are particuarly well written...
- No
__main__
- No documentation
- Everything is in
"main"
Pythonic Code
TBW
Loops, Context Managers, and List/Generator Comprehensions
This section is based on notes from CS 330 Object Oriented Programming & Design.
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++, Java, and Rust... we end up with...
Python | C++ | Java | Rust |
---|---|---|---|
list |
std::list |
java.util.List |
std::collections::LinkedList |
dict |
std::unordered_map |
java.util.HashMap |
std::collections::HashMap |
set |
std::unordered_set |
java.util.HashSet |
std::collections::HashSet |
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:
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:
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.
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:
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()
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
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.
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.
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:
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.
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.
Python File IO - Using
with
andgzip
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")
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 |
Libraries & pip
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.