ICT582 Python Revision
🎯 Learning Objectives
πŸ“š Key Concepts

OOP vs Procedural Programming

Procedural: Break the task into a sequence of steps. The steps are the focus.

OOP: Identify the objects in the problem. Design centres on objects and how they interact (like a diner, waiter and chef each playing their role).

You can write OOP-style code in non-OOP languages (like C), and you can write procedural-style code in an OOP language (like Python). What makes a program OOP is the design, not the language.

OOP Language Requirements

  • Encapsulation β€” Bundle data (state) and methods (behaviour) into one unit (a class). Hide internal details so users interact through a clean interface.
  • Inheritance β€” A subclass (child) can inherit data members and methods from a superclass (parent) and add its own.
  • Polymorphism β€” "Many forms." Objects of different classes can be treated as objects of a common superclass; related methods can share the same name.

Class and Object β€” The Blueprint Analogy

BlueprintClass
One blueprint, many housesOne class, many objects
Houses share same structureObjects share same structure
Blueprint needs no physical spaceClass needs no memory
Each house uses physical resourcesEach object uses memory

An object has state (data attributes) and behaviour (methods). A class is the template from which objects are created. An object is also called an instance of the class.

Class Definition Syntax

class ClassName:
    class_variable = value     # shared by ALL objects

    @classmethod
    def class_method(cls, ...):
        cls.class_variable = ...  # operates on class, not instance

    def __init__(self, param1, param2):
        self.attr1 = param1    # instance variable
        self.attr2 = param2    # instance variable

    def instance_method(self):
        ...                    # operates on this instance

__init__ β€” The Object Initialiser

__init__ is automatically called when you create a new object. It defines and initialises the instance variables.

class Coordinate:
    def __init__(self, xc, yc):
        self.x = xc   # self.x is an instance variable
        self.y = yc   # belongs to the whole object
        # xc and yc are local parameters

self is the first parameter of every instance method. It refers to the current object. (The name self is a convention β€” not required but always used.)

Class Variables vs Instance Variables

class Student:
    uni = "MU"                    # CLASS variable (shared)

    @classmethod
    def setUni(cls, u): cls.uni = u  # changes the shared copy

    def __init__(self, name, age):
        self.name = name          # INSTANCE variable (per object)
        self.age  = age

    def changeName(self, name): self.name = name

s1 = Student("John", 25)
s2 = Student("Mary", 23)

Student.setUni("UWA")
print(s1.uni)   # UWA  (both share the class variable)
print(s2.uni)   # UWA

s1.changeName("Peter")
print(s1.name)  # Peter
print(s2.name)  # Mary (unaffected)

print(Student.uni)   # UWA  (class var accessible by class name)
print(Student.name)  # AttributeError! name is an instance var

⚠️ Changing Class Variable via Object Reference

This is a trap! Assigning to a class variable via an object reference creates a new instance variable for that object only β€” it does NOT change the class variable.

s1.uni = "Curtin"      # creates instance var in s1 ONLY
print(s1.uni)          # Curtin  (s1's own copy)
print(s2.uni)          # UWA     (still the class variable)
print(Student.uni)     # UWA     (class variable unchanged)

Rule: Change class variables only via the class name: Student.uni = "..." or via a class method.

Data Types Are Objects

In Python, every value is an object of some built-in class:

ValueClassValueClass
121int[1,5,7]list
3.14float(2,7,8)tuple
"Hello"str{1,3,5}set
Truebool{"WA":"..."}dict
NoneNoneTyperange(10)range

Class Methods (@classmethod)

Use the @classmethod decorator. First parameter is cls (the class itself). Can only operate on class variables, not instance variables.

class Counter:
    count = 0

    @classmethod
    def increment(cls):
        cls.count += 1

Counter.increment()
Counter.increment()
print(Counter.count)   # 2
πŸ’» Code Examples

Example β€” BankAccount class

class BankAccount:
    interest_rate = 0.05   # class variable

    def __init__(self, owner, balance=0):
        self.owner   = owner      # instance variables
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        if amount > self.balance:
            print("Insufficient funds")
        else:
            self.balance -= amount

    def __str__(self):    # operator method for print()
        return f"{self.owner}: ${self.balance}"

acc1 = BankAccount("Alice", 1000)
acc2 = BankAccount("Bob")
acc1.deposit(500)
acc1.withdraw(200)
print(acc1)   # Alice: $1300
print(acc2)   # Bob: $0
⚠️ Exam Focus
  1. Know OOP vs procedural: OOP focuses on objects and their interactions.
  2. Explain encapsulation, inheritance, and polymorphism β€” definition questions are common.
  3. Distinguish class variable (shared, change via class name) vs instance variable (per object, created in __init__).
  4. Trace code with multiple objects: changing s1.name does NOT change s2.name.
  5. Know the @classmethod decorator and the role of cls vs self.
  6. Dangerous trap: obj.class_var = value creates an instance variable, not changes the class variable.
❌ Common Mistakes
⚑ Quick Recap
← Topic 08: Exceptions Topic 10: NumPy β†’