Defining a Class
Concepts covered: Decorators
Data that belongs together
A play count belongs to a track id. Held in t1_name and t1_plays as separate variables, the 2 values have nothing in the program tying them together, and a job tracking 500 tracks needs 1,000 variables. A class is a blueprint for an object that holds a group of variables, called attributes, together with the functions that work on them, called methods. Building an object from the blueprint is called making an instance.
The smallest useful class
class Tally:
def __init__(self, name):
self.name = name
self.plays = 0
t = Tally("t1")
print(t.name, t.plays)
print(type(t).__name__)Output:
t1 0 Tally
Line by line: class Tally: opens an indented block that defines the blueprint. def gives an indented block of code a name, and the block runs each time that name is called; functions get a lesson of their own later, and inside a class each one is a method. __init__ is the method Python calls when Tally("t1") runs, with self standing for the new object being built. self.name = name stores the argument on that object, and self.plays = 0 gives every new tally a starting count. The finished object is bound to t, and t.name reads the attribute back. type(t) reports the class it was built from, and that class's __name__ attribute holds its name, Tally, the way type(3).__name__ gives int.
Methods change their own object
a.add(3) is a shorthand: Python looks up add in Tally and calls it with a as self and 3 as count. The method changes a.plays and nothing else, so b keeps its own count. Two objects built from 1 class share the methods and hold separate attributes. The run below shows both objects on the stage as their counts move.
class Tally:
def __init__(self, name):
self.name = name
self.plays = 0
def add(self, count):
self.plays = self.plays + count
a = Tally("t1")
b = Tally("t2")
a.add(3)
a.add(4)
b.add(10)
print(a.name, a.plays)
print(b.name, b.plays)t1 7 t2 10
Returning a value
A method can hand a value back to its caller with return instead of printing it. The call then stands for that value, so it can be stored in a variable or passed straight to print. Below, share divides this tally's plays by a total it is given.
class Tally:
def __init__(self, name):
self.name = name
self.plays = 0
def add(self, count):
self.plays = self.plays + count
def share(self, total):
return self.plays / total
a = Tally("t1")
a.add(6)
print(a.share(24))Output:
0.25
Practice
What does the last line print?
class Box:
def __init__(self):
self.items = 0
def put(self, n):
self.items = self.items + n
x = Box()
y = Box()
x.put(2)
x.put(2)
y.put(5)
print(x.items, y.items)- 9 9
- 4 9
- 4 5
- 2 5
The self. prefix is what makes a change stick. Inside a method, ticks = ticks + 1 written without it names a temporary variable that has no value yet, so the call stops with UnboundLocalError: local variable 'ticks' referenced before assignment. Leaving self out of the header fails at the call instead, with the TypeError from the rule above. Both mistakes break the same contract: a method receives its object and writes to it.
class Meter:
def __init__(self):
self.ticks = 0
def tick(self):
ticks = ticks + 1About this lesson
This section is part of the Python Foundations: Advanced lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.