Exploring the Python Programming Language

Gregory M. Kapfhammer

January 22, 2024

What are the key features of the Python programming language?

  • Defining and evaluating expressions
  • Declaring and using variables with types
  • Creating and using collections

Thinking and writing about Python programs

  • Sequence: Run operations one after another in an order
  • Selection: Decide which operations will execute
  • Iteration: Repeat an operation a specific number of times

Sequence: Run operations one after another in a specified order

def detect() -> Dict[str, str]:
    """Run all of the sub-detects."""
    run_output: List[Dict[str, str]] = []
    run_output = execute.execute_by_name_filter(
        constants.project.Detect_Module, constants.project.Detect_Filter
    )
    return util.union_list_of_dicts(run_output)
  • Calling the detect function causes each line to run sequentially

  • Invoke execute_by_name_filter function with two inputs

  • Invoke the union_list_of_dicts function with one input

  • Return output of union_list_of_dicts function to caller

Selection: Decide which operations will execute with conditionals

if platform.system() == "Windows":
    total_disk = psutil.disk_usage("C:\\").total
    used_disk = psutil.disk_usage("C:\\").used
else:
    total_disk = psutil.disk_usage("/").total
    used_disk = psutil.disk_usage("/").used
  • The psutil module provides access to system information

  • The disk_usage function returns information about disk usage

  • But disk_usage needs different inputs for the filesystem root!

  • Conditional logic determines the input to disk_usage

Iteration: Repeat an operation a specific number of times

def union_list_of_dicts(container: List[Dict[str, str]]) -> Dict[str, str]:
    """Union a list of dictionaries into a single dictionary."""
    output: Dict[str, str] = {}
    for dictionary in container:
        output = {**output, **dictionary}
    return output
  • output is a dictionary that starts out empty

  • container is a list of dictionaries

  • The for loop iterates through each dictionary in container

  • The body of the loop merges the dictionaries into output

Collections contain multiple values

  • Strings: str in Python
  • Lists: list in Python
  • Tuples: tuple in Python
  • Dictionaries: dict in Python
  • Sets: set in Python

Let’s explore each of these in greater detail!

Creating and using a string

s = "Hello, "
t = "World."
u = s + t
print(type(u))
print(u)
print(u[9])
n = str(9876)
print(n[2])
<class 'str'>
Hello, World.
r
7
  • What is the purpose of the type function?
  • What is the purpose of the u[9] notation?
  • What is the purpose of the str function?
  • What is the purpose of the + operator?

Creating and using a list

numbers = [1,2,3,4,5,6]
print(type(numbers))
numbers.append(100)
print("The first item is", numbers[0])
print("The second item is", numbers[1])
print("The last item is", numbers[-1])
print("The second to last item is", numbers[-2])
numbers[2] = "skip"
numbers[3] = "a"
numbers[4] = "few"
numbers[-2] = 99
print(numbers)
<class 'list'>
The first item is 1
The second item is 2
The last item is 100
The second to last item is 6
[1, 2, 'skip', 'a', 'few', 99, 100]

What does this illustrate about the list type in Python?

Creating and using a tuple

data = (1, 2, "skip a few", 99, 100)
print(type(data))
print(data)
print(data[4])
<class 'tuple'>
(1, 2, 'skip a few', 99, 100)
100
  • What are some invalid operations on a tuple?
    • data[4] = 100
    • data.append(100)
    • data.remove(100)
    • data.insert(100)
    • data.pop(100)

Creating and using a dictionary

d = dict()
d[5] = "five"
d[2] = "two"
d["pi"] = 3.1415926
print(type(d))
print(d)
print(d["pi"])
<class 'dict'>
{5: 'five', 2: 'two', 'pi': 3.1415926}
3.1415926
  • The dict function creates an empty dictionary called d
  • Dictionaries store key-value pairs like {5: 'five'} and {2: 'two'}
  • The keys can be of any data type that is hashable like int
  • The values can be of any data type like str and float
  • It is possible to lookup a value by its key as in d["pi"]

Creating and using a set

values = {2,1}
print(type(values))
values.add(3)
values.add(2)
values.add(2)
values.add(2)
print(values)
<class 'set'>
{1, 2, 3}
  • Sets do not store duplicate values
  • The data in a set must be hashable
  • The add function places more data in a set
  • Repeated calls of add with 2 do not change the set
  • Be careful, {} is an empty dictionary!

Common operations to perform on a collection

  • Determine the length of a collection
  • Add an element to or remove element from a collection
  • Access an element in a collection
  • Determine if a collection contains an element
  • Iterate through all of the elements in a collection
  • Slice a collection to get a subset of its elements

Sizing and slicing collections

a = "a string"
b = ["my", "second", "favorite", "list"]
c = (1, "tuple")
d = {"a": "b", "b": 2, "c": False}
e = {1,2,3,4,4,4,4,2,2,2,1}
print(len(a), len(b), len(c), len(d), len(e))
8 4 2 3 4

a = "a string"
b = ["my", "second", "favorite", "list"]
c = (1, 2,3,"tuple")
print(a[3:7])
print(a[1:-2])
print(b[1:])
print(c[:2])
trin
 stri
['second', 'favorite', 'list']
(1, 2)

Iterating through lists and tuples

mylist = [1,3,5]
mytuple = (1, 2, "skip a few", 99, 100)
print("List:")
for item in mylist:
  print("  " + str(item))
print()
print("Tuple:")
for item in mytuple:
  print("  " + str(item))
List:
  1
  3
  5

Tuple:
  1
  2
  skip a few
  99
  100

Iterating through sets and strings

myset = {"a", "b", "z"}
mystring = "abz"

print("Set:")
for element in myset:
  print("  " + element)

print()
print("String:")
for character in mystring:
  print("  " + character)
Set:
  b
  z
  a

String:
  a
  b
  z

Iterating through a dictionary

mydict = {"a": 96, "b": 97, "c": 98}
for key in mydict:
  print(key, mydict[key])
print()
for key, value in mydict.items():
  print(key, value)
print()
for key in mydict.keys():
  print(key, mydict[key])
a 96
b 97
c 98

a 96
b 97
c 98

a 96
b 97
c 98

Containment checking for collections

a = "a string"
b = ["my", "second", "favorite", "list"]
c = (1, "tuple")
d = {"a": "b", "b": 2, "c": False}
e = {1,2,3,4,4,4,4,2,2,2,1}
print("str" in a)
print("string" in a)
print("my" in b)
print("tuple" in c)
print("a" in d)
print("b" in d)
print(4 in e)
True
True
True
True
True
True
True

What are the performance trade-offs associated with checking to see if a collection contains a value?

  • Questions to consider when designing an experiment:
    • Type of the collection?
    • Contents of the collection?
    • Size of the collection?
    • How often will the collection change?
    • How can we measure time and space overhead?

Key features of Python

Defining and evaluating expressions

expression = 5 + 3 * 2
print(expression)
11

Declaring and using variables with types

integer_variable = 10
float_variable = 20.5
string_variable = "Hello, World!"
print(integer_variable, float_variable, string_variable)
10 20.5 Hello, World!

Creating and using collections

list_collection = [1, 2, 3, 4, 5]
print(list_collection)
[1, 2, 3, 4, 5]