A class without methods is like a zombie without a brain: it exists but does nothing. 🧟
Methods are the actions an object can perform. Let’s bring our objects to life!
🎯 What is a method?
A method = a function that belongs to an object.
Syntax
class ClassName:
def method_name(self, parameters):
# Method body
pass
Key difference from plain functions:
- ❌ Function: def groan(zombie):
- ✅ Method: def groan(self):
A method always takes self as its first parameter!
🧟 Example: Zombie makes a sound
class Zombie:
def __init__(self, name):
self.name = name
def groan(self): # ← Method
print(f"{self.name}: Braaaains! 🧟")
walker = Zombie("Walker")
walker.groan() # Walker: Braaaains! 🧟
What happens?
walker.groan()calls the method- Python automatically passes
walkerasself - The method runs using
self.name
🔄 Methods with parameters
A method that accepts arguments
class Zombie:
def __init__(self, name, health):
self.name = name
self.health = health
def take_damage(self, damage): # ← Parameter: damage
self.health -= damage
print(f"{self.name} took {damage} damage!")
print(f"Health: {self.health}")
walker = Zombie("Walker", 50)
walker.take_damage(20)
# Walker took 20 damage!
# Health: 30
Notice:
- Method signature: def take_damage(self, damage) — 2 parameters
- Call site: walker.take_damage(20) — 1 argument
Why? Python automatically passes walker as self!
Multiple parameters
class Human:
def __init__(self, name, health):
self.name = name
self.health = health
def attack(self, target, weapon_damage):
damage = weapon_damage + 10 # Base damage + weapon bonus
target.health -= damage
print(f"{self.name} attacks {target.name}!")
print(f"Damage: {damage}")
rick = Human("Rick", 100)
walker = Zombie("Walker", 50)
rick.attack(walker, 15)
# Rick attacks Walker!
# Damage: 25
📤 Methods with return values
class Zombie:
def __init__(self, name, health):
self.name = name
self.health = health
def is_alive(self): # ← Returns True/False
return self.health > 0
def attack(self): # ← Returns damage dealt
import random
return random.randint(5, 15)
walker = Zombie("Walker", 30)
# Use the returned value
if walker.is_alive():
damage = walker.attack()
print(f"Zombie attacks! Damage: {damage}")
else:
print("Zombie is dead")
Why return?
- A method can return the result of a computation
- You can use it in conditions, assignments, etc.
🔗 Methods calling other methods
class Zombie:
def __init__(self, name, health):
self.name = name
self.health = health
def groan(self):
print(f"{self.name}: Braaaains!")
def walk(self):
print(f"{self.name} is walking...")
def approach(self): # ← Calls other methods!
self.walk()
self.groan()
print(f"{self.name} is getting closer!")
walker = Zombie("Walker", 50)
walker.approach()
# Walker is walking...
# Walker: Braaaains!
# Walker is getting closer!
self.walk() = “Call the walk method on this object.”
🎮 Objects interacting through methods
Methods can modify other objects!
class Human:
def __init__(self, name, health):
self.name = name
self.health = health
self.kills = 0
def attack(self, zombie):
damage = 20
zombie.health -= damage # ← Modify another object!
print(f"{self.name} attacks {zombie.name}!")
if zombie.health <= 0:
print(f"{zombie.name} is defeated!")
self.kills += 1
class Zombie:
def __init__(self, name, health):
self.name = name
self.health = health
rick = Human("Rick", 100)
walker = Zombie("Walker", 40)
rick.attack(walker)
# Rick attacks Walker!
rick.attack(walker)
# Rick attacks Walker!
# Walker is defeated!
print(f"Kills: {rick.kills}") # 1
This is the magic of OOP: Objects communicate through methods! 🌟
📝 Methods modifying attributes
class Human:
def __init__(self, name):
self.name = name
self.health = 100
self.ammo = 12
def shoot(self):
if self.ammo > 0:
self.ammo -= 1 # ← Update attribute
return True
else:
print("Out of ammo!")
return False
def reload(self):
self.ammo = 12 # ← Update attribute
print(f"{self.name} reloaded!")
def heal(self, amount):
self.health += amount # ← Update attribute
if self.health > 100:
self.health = 100 # Cap at 100
print(f"{self.name} healed {amount} HP. Health: {self.health}")
rick = Human("Rick")
rick.shoot() # Fires (ammo: 11)
rick.heal(20) # Rick healed 20 HP. Health: 100
🛠️ Types of methods
1. Getters (reading data)
class Zombie:
def __init__(self, health):
self.health = health
def is_alive(self): # ← Getter
return self.health > 0
def get_status(self): # ← Getter
if self.health > 30:
return "Healthy"
elif self.health > 0:
return "Wounded"
else:
return "Dead"
2. Setters (writing data)
class Zombie:
def __init__(self, health):
self.health = health
def set_health(self, new_health): # ← Setter
if new_health < 0:
self.health = 0
else:
self.health = new_health
3. Actions (performing operations)
class Zombie:
def __init__(self, name):
self.name = name
def attack(self): # ← Action
print(f"{self.name} attacks!")
return 10
def groan(self): # ← Action
print(f"{self.name}: Braaaains!")
⚠️ Common mistakes
Mistake 1: Forgot self
class Zombie:
def __init__(self, name):
self.name = name
def groan(): # ❌ No self!
print("Braaaains!")
walker = Zombie("Walker")
walker.groan() # TypeError: groan() takes 0 positional arguments but 1 was given
Fix:
def groan(self): # ✅ Added self
Mistake 2: Accessing an attribute without self
class Zombie:
def __init__(self, name):
self.name = name
def groan(self):
print(f"{name}: Braaaains!") # ❌ Missing self!
walker = Zombie("Walker")
walker.groan() # NameError: name 'name' is not defined
Fix:
print(f"{self.name}: Braaaains!") # ✅ self.name
Mistake 3: Calling a method without parentheses
walker = Zombie("Walker", 50)
damage = walker.attack # ❌ No ()
print(damage) # <bound method Zombie.attack of <__main__.Zombie object at 0x...>>
Fix:
damage = walker.attack() # ✅ With parentheses
📊 Function vs Method comparison
Plain function (from before OOP)
def zombie_attack(zombie):
return 10
def human_attack(human, zombie):
zombie["health"] -= 20
walker = {"name": "Walker", "health": 50}
human_attack(rick, walker)
Problems:
- ❌ Functions and data are separate
- ❌ Easy to pass wrong arguments
- ❌ No link between data and behavior
Method (OOP style)
class Human:
def attack(self, zombie):
zombie.health -= 20
rick = Human("Rick", 100)
walker = Zombie("Walker", 50)
rick.attack(walker)
Advantages:
- ✅ The method belongs to the object
- ✅ Clear who does what
- ✅ Data and behavior are together
💡 Best practices
✅ Good methods:
1. Descriptive names
def is_alive(self): # ✅ Clear what it returns
def attack(self): # ✅ Clear what it does
2. Single responsibility
def shoot(self):
if self.ammo > 0:
self.ammo -= 1
return True
return False
# ✅ Only shoots, nothing else
3. Return values when appropriate
def is_alive(self):
return self.health > 0 # ✅ Returns a result
❌ Bad methods:
1. Vague names
def do(self): # ❌ What does it do?
def proc(self): # ❌ What does it process?
2. Doing too many things
def do_everything(self):
self.shoot()
self.reload()
self.heal(20)
self.walk()
# ❌ Too many responsibilities!
📝 Checklist
- [ ] I know how to define a method inside a class
- [ ] I understand that
selfis always the first parameter - [ ] I can pass arguments to a method
- [ ] I can return values from a method (
return) - [ ] I understand how methods modify attributes
- [ ] I understand how methods call other methods
- [ ] I understand how objects interact through methods
🚀 Summary
A method is a function that belongs to an object.
Syntax:
class ClassName:
def method_name(self, parameters):
# Body
return result
Calling a method:
object.method(arguments)
Key points:
- ✅ Always takes self as the first parameter
- ✅ Can access attributes (self.attribute)
- ✅ Can call other methods (self.method())
- ✅ Can modify attributes (self.attribute = new_value)
- ✅ Can return values (return)
Core idea: Methods are the actions of objects. Objects interact and change each other through their methods!
Next step: Learn how to display objects beautifully using __str__! 🎨
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!