Python exercises#

Python as a calculator#

You can use the Python as a simple calculator:

1 + 2
4.5 / 3 - (1 + 2) * 3

Use ** to compute the power:

4**5

Python also supports complex numbers:

a = 1 + 2j
b = 3 - 5j
a * b

“Modulo” (%) computes the remainder of integer division

10 % 2
10 % 3
for n in range(10):
    print(f"{n} % 3 = {n % 3}")

Division is exact in Python 3, even if both numbers are integers

3 / 2

Integer division can be done with // and always returns an integer

3 // 2

More advanced mathematical functions can be imported:

from math import log10

log10(100)
help(log10)
from math import log

Some exercises adapted from Practice Python, used under CC-BY-4.0.

Exercise#

starting from either a variable or a command-line, print whether a number is odd or even.

Modify hw.py.

Bonus: accept any number of arguments

For example:

$ python3 hw.py 5
5 is odd!
$ python3 hw.py 123456
123456 is even!

Bonus: show both quotient and remainder when given two integers

$ python3 hw.py 5 3
7 / 3 = 2 remainder 1
import sys

...

Exercise#

Given a list, return all of the even items.

For example, given [1, 2, 3, 4] return [2, 4].

def get_even(input_list):
    """Return even items found in a list"""
    even_items = []
    ...
    return even_items


get_even([1, 2, 3, 4])

Exercise#

Given a list, return a dictionary of the counts of even and odd items

For example, given [0, 1, 2, 3, 4] return {“even”: 2, “odd”: 3}.

def get_even_counts(input_list):
    """Return dict of"""
    counts = {}
    ...
    return counts

Exercise#

  1. list all the files in a directory

  2. in alphabetical order (bonus: case-insensitive!)

  3. at the end, show counts by file extension

paths = ...
sorted_paths = ...
extension_counts = {}

for path in sorted_paths:
    ...

Subclassing shapes#

Let’s define a base shape class with methods to calculate area and perimiter:

class Shape:
    """A class defining Shapes"""

    def __str__(self):
        return f"I am a {self.__class__.__name__}"

    def area(self):
        raise NotImplementedError()

    def perimiter(self):
        raise NotImplementedError()

This base class defines an API for shapes. Subclasses can impelement this API by overriding these methods.

Now we can make a subclass, Rectangle, which has a width and height:

class Rectangle(Shape):
    """A rectangle"""

    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimiter(self):
        return 2 * (self.width + self.height)


r = Rectangle(3, 4)
print(r)
print(f"area = {r.area()}")
print(f"perimiter = {r.perimiter()}")
I am a Rectangle
area = 12
perimiter = 14

Excercise#

Define a Square shape as simply as you can, such that the constructor takes only one argument:

sq = Square(5)
sq.area() # 25
sq.perimiter() # 20

and define a Circle class that takes a radius:

circ = Circle(radius=5)
circ.area()  #
circ.perimiter()
class Square(...):
    ...


sq = Square(5)
print(sq)
print(f"area = {sq.area()}")
print(f"perimiter = {sq.perimiter()}")
import ...
class Circle(...):
    ...

circ = Circle(radius=5)
print(circ)
print(f"area = {circ.area()}")
print(f"perimiter = {circ.perimiter()}")

Overriding operators with magic methods#

__add__ and __mul__ are the methods for addition and multiplication.

Check out the Python data model for what operator methods are called.

class MyNumber:
    def __init__(self, n):
        self.n = n

    def __repr__(self):
        return f"MyNumber({self.n})"

    def __add__(self, other):
        if not isinstance(other, MyNumber):
            raise TypeError("Can only add MyNumbers together")
        return MyNumber(self.n + other.n)

    def __mul__(self, other):
        if not isinstance(other, MyNumber):
            raise TypeError("Can only multiply MyNumbers together")
        return MyNumber(self.n * other.n)


a = MyNumber(5)
b = MyNumber(10)
a + b
a * b

But we can’t add a together with a regular Python int!

a + 1

Exercise#

allow multiplication / addition to accept regular Python floats and ints, in addition to MyNumber classes.

class MyNumber:
    def __init__(self, n):
        self.n = n

    def __repr__(self):
        return f"MyNumber({self.n})"

    def __add__(self, other):
        if not isinstance(other, MyNumber):
            raise TypeError("Can only add MyNumbers together")
        return MyNumber(self.n + other.n)

    def __mul__(self, other):
        if not isinstance(other, MyNumber):
            raise TypeError("Can only multiply MyNumbers together")
        return MyNumber(self.n * other.n)


a = MyNumber(5)
print(a + 10)
print(a * 2)

Exercise#

define a Point class which supports addition and subtraction of other Points and multiplication by a scalar (int or float).

Bonus: implement a 3d Point3d class with x, y, z

Bonus: implement a dot product with the @ matrix multiplication operator:

a @ b -> scalar

Bonus: implement an n-dimensional Point class that works for any number of dimensions:

v = Point(1, -2, 5, 6)
len(v)  # 4
u = Point(-1, 2, -5, -6) 
u + v  #  (0, 0, 0, 0)
class Point:
    def __init__(self, x, y):
        ...
    
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    
    def __add__(self, other):
        ...
    
    def __mul__(self, n):
        ...

    def __...__(self, other):
        ...