Objects as arguments
A function can change the object it gets
You have written functions that change an object they get. Now you can see why that works: when you call a function with an object, the parameter refers to the same object as the argument. Nothing is copied. So when the function changes the object's attributes, the caller sees the change after the call, just as with lists in the References module:
class Hero:
def __init__(self, name):
self.name = name
self.level = 1
def __str__(self):
return f"{self.name} (level {self.level})"
def level_up(hero):
hero.level += 1
ayla = Hero("Ayla")
print(ayla)
level_up(ayla)
level_up(ayla)
print(ayla)
Ayla (level 1)
Ayla (level 3)During the call, hero inside the function and ayla outside it are two names for one object.
There is one catch. Giving the parameter a new value inside the function, such as hero = Hero("Bram"), only makes the local name refer to another object. The caller's variable still refers to the old one. To change the caller's object, change its attributes.
A function can create an object
A function can also create a new object and return it. The caller gets a reference to it, and can keep it in a variable or a list. This function turns a line of text into a Hero:
class Hero:
def __init__(self, name):
self.name = name
self.level = 1
def __str__(self):
return f"{self.name} (level {self.level})"
def hero_from_text(line):
parts = line.split(";")
hero = Hero(parts[0])
hero.level = int(parts[1])
return hero
team = []
for line in ["Ayla;3", "Bram;5"]:
team.append(hero_from_text(line))
for hero in team:
print(hero)
Ayla (level 3)
Bram (level 5)The object created inside the function lives on after the function ends, because the caller still has a reference to it.
A method can take an object too
Methods are functions that belong to a class, so they can take objects as arguments as well. A method that gets an object of another class can read and change that object, and its own object at the same time. Here a coach trains athletes: training makes the athlete faster, and the coach counts the sessions.
class Athlete:
def __init__(self, name, speed):
self.name = name
self.speed = speed
class Coach:
def __init__(self, name, boost):
self.name = name
self.boost = boost
self.sessions = 0
def train(self, athlete):
athlete.speed += self.boost
self.sessions += 1
print(f"{self.name} trained {athlete.name}, speed now {athlete.speed}")
mia = Athlete("Mia", 20)
tom = Athlete("Tom", 25)
ray = Coach("Coach Ray", 3)
ray.train(mia)
ray.train(mia)
ray.train(tom)
print("Sessions:", ray.sessions)
Coach Ray trained Mia, speed now 23
Coach Ray trained Mia, speed now 26
Coach Ray trained Tom, speed now 28
Sessions: 3Inside train, self is the coach the method is called on (the object before the dot), and athlete is the athlete in the parentheses. One call, ray.train(mia), changes both objects: Mia's speed and Ray's count of sessions.