Python: Classes and Instances + Class Variables

Michael Wirtz
4 min readMar 27, 2021

Introduction

In taking a quick break from ESG-related data collection and analysis, I believed it was important to return to Object Oriented Programming (OOP). This move will come in handy down the line when I move to create my algorithmic trading bot because of the flexibility and simplicity that OPP provides. It allows for code to be packaged, and it allows you to modify the data within the package. For this post, we will be diving into two specific aspects of OOP: (1) classes and instances and (2) class variables.

Classes and Instances

Let’s start with the conceptual basis for this article. A class is essentially a blueprint for creating instances. In the code below, each player represents an instance of the class. And to initialize this class, you must use the __init__ method. As you will see below, the first argument of the __init__ method is “self”. When you create an instance of the class, the __init__ method receives the first argument automatically. By convention, this argument should be named “self”. Take a look at the syntax here:

class Player:

# Runs every time you create new instance
def __init__(self, first, last, team, pay):
# Each instance will be set as self
# Instance variables
self.first = first
self.last = last
self.team = team
self.pay = pay
# Instances
player_1 = Player('Tom','Brady', 'Buccaneers', 25000000)
player_2 = Player('Aaron','Rodgers', 'Packers', 20000000)

To take this a step further, let’s check out methods. A regular method takes in the self argument and can be used, as an example, to return a player bio. Check out the example here:

class Player:

# Runs every time you create new instance
def __init__(self, first, last, team, pay):
# Each instance will be set as self
# Instance variables
self.first = first
self.last = last
self.team = team
self.pay = pay

# Each regular method automatically takes instance as first argument
def bio(self):
return ('{} {} plays for the {} and made ${} last year'.format(self.first, self.last, self.team, self.pay))

player_1 = Player('Tom','Brady', 'Buccaneers', 25000000)
player_2 = Player('Aaron','Rodgers', 'Packers', 20000000)
# Need parentheses when calling a method
player_1.bio()
Output: 'Tom Brady plays for the Buccaneers and made $25000000 last year'

If you don’t remember to use parentheses when calling a method, you will receive an error. Notice how the code becomes highly functional while maintaining its simplicity.

Class Variables

Here, I am just going to first give you the code, and then I’m going to walk you through what is going on. Therefore, don’t expect to understand what is going on yet, but refer back to it as you continue reading.

class Player:

recorded_players = 0
performance_incentive = 0.15

def __init__(self, first, last, team, pay):
self.first = first
self.last = last
self.team = team
self.pay = pay

# Use Player not self because there isn't use case
# for different values of recorded_players
Player.recorded_players += 1
def bio(self):
return ('{} {} plays for the {} and made ${} last year'.format(self.first, self.last, self.team, self.pay))

def apply_incentive(self):
self.pay = int(self.pay * (1 + self.performance_incentive))

player_1 = Player('Tom','Brady', 'Buccaneers', 25000000)
player_2 = Player('Aaron','Rodgers', 'Packers', 20000000)

Above, there are two class variables. First, you can see the recorded_players variable. This variable simply tracks the number of instances of the Player class that exist. Since the __init__ method runs for each new instance, this variable will be a helpful tracker of the total number of player instances. Second, we have the performance incentive class variable. This variable is set in the case that a player meets a certain performance threshold. The class variable is defined as 0.15, meaning that a player will receive a pay bump of 15% if we apply the incentive. Here is where something interesting happens. Before we continue, notice how, in the apply_incentive method, we use “self.performance_incentive” rather than “Player.performance_incentive”. Check out these two examples below to see why we would want to do this:

# Example 1Player.performance_incentive = 0.20print(Player.performance_incentive)
print(player_1.performance_incentive)
print(player_2.performance_incentive)
Output:
0.2
0.2
0.2
# Example 2player_1.performance_incentive = 0.12print(Player.performance_incentive)
print(player_1.performance_incentive)
print(player_2.performance_incentive)
Output:
0.2
0.12
0.2

By using self instead of Player, we allow for the class variable to be changed for each instance. Let’s say that Tom Brady’s performance incentive ended up being 20% while Aaron Rodgers’ performance incentive is 30%. By defining the performance incentive for each instance, we can accomodate for this inconsistency. The use of “self” allows us to have this appreciated level of flexibility.

Conclusion

Above was a basic introduction to two entry-level topics in OOP. In general, OOP is a crucial point of understanding for all those looking to advance their programming skills. A great video resource for this topic in general comes from one of my favorite YouTube programming helpers, Corey Schafer. If you don’t know who he is, I would suggest checking out his content immediately. Below, I’ve got the link to his series on OOP, which is the basis for this article.

--

--