Closure#

Syllabus Week 10: Classes I#

  • Object-oriented programming, structuring code to bundle properties and behavior.

  • Classes, templates for creating instances that share common attributes and methods.

  • Instances, concrete objects created from a class template.

  • Keyword class

  • Class naming convention

  • Attributes

  • Objects are mutable

  • Methods and the argument self

  • Method __init__()

Advanced#

Note about the material in Advanced section. The advanced material contains more some additional topics related to the weeks’s content. You are not required to read this material, and none of the exercises or exam questions will rely on this material.

Advanced 10.1: More Examples#

As already mentioned, we can give other objects of the same class as arguments to the class methods. Consider this example where this is done.

class Dog:
    def __init__(self, name, age, race, sex):
        self.name = name
        self.age = age
        self.race = race
        self.sex = sex

    def make_n_years_older(self, num_years):
        self.age = self.age + num_years

    def get_description(self):
        description = f"The dog is a {self.race} and its name is {self.name} and it is {self.age} years old"
        return description

    def is_adult(self,):
        return self.age > 1

    def can_mate_with(self, other):
        if self.is_adult() and other.is_adult():
            if self.sex != other.sex:
                return True
        return False


my_dog = Dog('Fiddo', 2, 'Border Collie', 'male')
other_persons_dog = Dog('Fiona', 0.1, 'Border Collie', 'female')
if my_dog.can_mate_with(other_persons_dog):
    print("My dog can mate with the other person's dog")
else:
    print("My dog cannot mate with the other person's dog")

Look at the following example where we return a new object with the modified attributes. That allows us to keep the original object unchanged, so we can use both the original and the modified object.

import math
class TwoDimensionalVector:
    def __init__(self, x, y):
        self.as_list = [x, y]

    def multiply_by_scalar(self, scalar):
        new_values = []
        for idx in range(2):
            new_values.append(scalar * self.as_list[idx])
        return TwoDimensionalVector(new_values[0], new_values[1])

    def vector_norm(self):
        norm = 0
        for idx in range(2):
            norm = norm + self.as_list[idx] ** 2
        return math.sqrt(norm)

vector = TwoDimensionalVector(2, 3)
twice_as_long_vector = vector.multiply_by_scalar(2)

if (vector.vector_norm() * 2 == twice_as_long_vector.vector_norm()):
    print('Oh yes, perfect now the world makes sense')
print(vector.vector_norm())
print(twice_as_long_vector.vector_norm())

Advanced 10.2: Working with Objects#

Objects can be treated as any other data type. We can assign them to variables, pass them as arguments to functions, and return them from functions. In the following example, we make a list of user-defined objects.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

persons = []
for name in ['Alice', 'Bob', 'Charlie']:
    person = Person(name, 20)
    persons.append(person)

for person in persons:
    print(f"{person.name} is {person.age} years old")

Advanced 10.3: Objects Everywhere#

In Python, everything is an object. Check out the following example.

def my_function(a):
    return a + 1

print(type(my_function))

something = my_function
print(something(1))

print(type(something))

Functions are objects of the class function. This means that we can treat functions as any variable. Try to run the following code.

def english_greeting(name):
    print('Hi ' + name)

def spanish_greeting(name):
    print('Hola ' + name)

def german_greeting(name):
    print('Hallo ' + name)

def danish_greeting(name):
    print('Hej ' + name)


for greeting in [english_greeting, spanish_greeting, german_greeting, danish_greeting]:
    greeting('John')
    

Even classes are objects, the objects of the class type. Try to run the following code.

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

print(type(Dog))

Cat = Dog
my_cat = Cat('Mis', 2)

print(type(Cat))