HelloGrade Logo

HelloGrade

Python Classes: Blueprints for Cleaner Code

Published on: April 3, 2025 by Henson M. Sagorsor



Python Class Syntax Examples

What is a Class?

A template that defines the structure and behavior of objects.

code Attributes

Variables that store object data

self.name = "Buddy"

Stored in each object's memory

functions Methods

Functions that define behavior

def bark(self): print("Woof!")

Operate on the object's data

terminal Class Declaration Syntax

  class ClassName:
      def __init__(self, params):  # Constructor
          self.attr = params       # Attribute init
      
      def method_name(self):     # Method
          # Function body
class def self __init__

integration_instructions Practical Implementation

      class User:
          def __init__(self, username, email):
              self.username = username  # String attribute
              self.email = email        # String attribute
              self.login_count = 0      # Integer attribute
          
          def login(self):             # Method
              self.login_count += 1
              print(f"{self.username} logged in")

→ Usage: user1 = User("alice", "alice@example.com")

→ Key Point: Attributes define state, methods define behavior.

compare Class vs Module: When to Use Each

Classes Modules
class DataProcessor:
          def __init__(self, data):
              self.data = data
# processor.py
      def clean_data(data):
          return data.strip()
  • Need multiple instances
  • Require state management
  • Single stateless functionality
  • Utility functions collection

Pro Tip: Use modules for utilities, classes when you need to create objects with identity.


Objects (Instances)

Concrete individual units created from a class blueprint.

create Instantiation

  my_dog = Dog("Buddy", 3)  # Creates object
  print(my_dog.name)        # Access attribute

fingerprint Object Identity

  print(id(my_dog))         # Unique memory address
  print(type(my_dog))       # Returns: <class '__main__.Dog'>
memory Memory Representation
my_dog
Reference
Dog Object
name: "Buddy"
age: 3
__class__: Dog

edit Instance Mutability

  dog1 = Dog("Buddy", 3)
  dog2 = Dog("Max", 5)
  
  # Modify instance attribute
  dog1.age = 4

Key Behavior:

  • Changes to dog1 don't affect dog2
  • Each object maintains independent state

architecture Practical Usage Patterns

Collections of Objects

  dogs = [Dog("Buddy", 3), 
          Dog("Max", 5)]

Object as Arguments

  def print_dog_age(dog_obj):
      print(dog_obj.age)

Dynamic Attributes

  dog1.breed = "Golden"  # Added at runtime


The __init__ Method

The constructor that initializes new object instances.

schedule

Automatic Execution Timeline

  1. my_obj = MyClass() → Python allocates memory
  2. __new__ method creates raw object (implicit)
  3. __init__ initializes object state
  4. Reference assigned to my_obj

input Required Parameters

  class User:
      def __init__(self, username):  # Mandatory
          self.username = username
  
  # user = User()  # ERROR: missing username

Forgetting arguments raises TypeError

settings Default Values

  class Account:
      def __init__(self, balance=0):  # Optional
          self.balance = balance
  
  acc = Account()  # Uses balance=0

Default args enable flexible instantiation

construction Advanced Initialization Techniques

Type Validation

  def __init__(self, name: str):
      if not isinstance(name, str):
          raise TypeError("Name must be string")
      self.name = name

Computed Attributes

  def __init__(self, first, last):
      self.fullname = f"{first} {last}"  # Derived value

warning Critical Mistakes

❌ Mutable Default Arguments

  def __init__(self, items=[]):  # Dangerous!
      self.items = items

All instances share the same list. Use None instead.

❌ Forgetting self

  def __init__(name):  # Missing self
      self.name = name

Raises TypeError: __init__() takes 1 positional argument...


Instance vs. Class Attributes

Understand where data lives and how it's shared.

Instance Attributes Class Attributes
  class Dog:
      def __init__(self, name):
          self.name = name  # Per-instance
  
  dog1 = Dog("Buddy")
  dog2 = Dog("Max")
  • Stored in individual objects
  • Unique to each instance
  • Defined in __init__ or methods
  class Dog:
      species = "Canis familiaris"  # Shared
  
  dog1 = Dog()
  dog2 = Dog()
  • Stored in the class itself
  • Shared across all instances
  • Defined at class level

memory Memory Allocation

Dog Class
species: "Canis familiaris"
dog1
→ name: "Buddy"
→ __class__: Dog
dog2
→ name: "Max"
→ __class__: Dog

Class attributes exist once in memory, instance attributes are per-object

warning Shadowing Class Attributes

  class Dog:
      species = "Canis familiaris"
  
  dog1 = Dog()
  dog1.species = "Felis catus"  # Creates instance attribute
  
  print(Dog.species)  # Original unchanged: "Canis familiaris"

Instance assignment doesn't modify class attribute

update Dynamic Class Changes

  Dog.species = "Canis lupus"  # Affects all instances
  
  print(dog1.species)  # "Canis lupus" (if no shadowing)
  print(dog2.species)  # "Canis lupus"

Class-level changes propagate to instances

rule When to Use Each

✅ Use Instance Attributes For:

  • Object-specific state (name, age, balance)
  • Mutable data unique to each instance

✅ Use Class Attributes For:

  • Constants (DEFAULT_SIZE, MAX_LIMIT)
  • Shared configuration across instances

Common Mistakes

error

1. Missing self Parameter

  class Dog:
      def bark():  # Missing self
          print("Woof!")

❌ Error Triggered:

TypeError: bark() takes 0 positional arguments but 1 was given

Python automatically passes the instance as first argument.

✅ Fix:

def bark(self):

All instance methods must take self as first parameter.

warning

2. Mutable Default Arguments

  class ShoppingCart:
      def __init__(self, items=[]):  # Dangerous!
          self.items = items

❌ Hidden Behavior:

cart1 = ShoppingCart()
  cart1.items.append("Apple")
  cart2 = ShoppingCart()
  print(cart2.items)  # ['Apple'] 😱

Default list is created once at class definition.

✅ Fix:

def __init__(self, items=None):
      self.items = items or []

Use None and initialize per-instance.

compare_arrows

3. Class vs Instance Attribute Confusion

  class Counter:
      count = 0  # Class attribute
      
      def increment(self):
          self.count += 1  # Accidentally creates instance attr

❌ Unexpected Output:

c1 = Counter()
  c1.increment()
  c2 = Counter()
  print(c2.count)  # 0 (Expected 1)

+= creates new instance attribute instead of modifying class attr.

✅ Fix:

def increment(self):
      Counter.count += 1  # Explicit class reference

Or use @classmethod for class-level operations.


auto_awesome

You're Now a Class Designer!

In this lesson, you've transformed from writing procedural scripts to architecting object-oriented systems. You can now:

  • Design classes that logically bundle data and behavior
  • Instantiate objects with independent state
  • Leverage __init__ for clean object initialization
  • Choose between class vs instance attributes strategically

Expand Your Knowledge

Dive deeper into technology and productivity with these related articles:


quiz Test Your Knowledge

Validate your understanding of classes with a quiz.

assignment_turned_in Start Quiz Now


We'd Like to Hear Your Feedback

Comments

No comments yet. Be the first to share your thoughts!