Exploring Python's Class
Class Variables and Instance Variables
There are two types of variables that can be declared in a class: class variables and instance variables.
class Dog:
# This is a class variable
species = "Canis familiaris"
def __init__(self, name, age):
# These are instance variables
self.name = name
self.age = age
Class Variables
Class variables, also known as class attributes, are variables that are shared by all instances of a class. They are defined within the class but outside any of the class's methods. Class variables are not as common as instance variables.
▶ In this Dog
class, species
is a class variable. All instances of Dog
will have the same species
.
Instance Variables
Instance variables, also known as instance attributes, are variables that are unique to each instance. They are defined within methods and are usually set in the __init__
method, which is called when an object is created.
▶ In the Dog
class above, name
and age
are instance variables. They are set in the __init__
method and can have different values for different Dog
objects.
Accessing Class and Instance Variables
You can access class variables and instance variables using dot notation. Here's how you can access the species
, name
, and age
of a Dog
object:
# Create a Dog object
d = Dog('Fido', 3)
# Access the species, name, and age
print(d.species) # Outputs: Canis familiaris
print(d.name) # Outputs: Fido
print(d.age) # Outputs: 3
▶ In the above code, d.species
gives us the class variable species
, and d.name
and d.age
give us the instance variables name
and age
.
Remember, if you change a class variable, it will change for all instances of the class. But if you change an instance variable, it will only change for that instance.
Instance methods vs. Class methods vs. Static methods
There are three types of methods that can be defined within a Python's class: Instance Methods, Class Methods, and Static Methods. Each of these methods serves a different purpose and has different behavior. Let's explore each one along with examples:
Instance Methods
Instance methods are the most common type of methods in Python classes. They operate on instance-level data and have access to instance variables, class variables and other instance methods. The first parameter of an instance method is always 'self', which is a reference to the instance that is calling the method.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f"Hi, I'm {self.name}, and I'm {self.age} years old."
# Creating Dog instances
dog1 = Dog("Buddy", 3)
# Calling the instance method
print(dog1.introduce()) # Output: Hi, I'm Buddy, and I'm 3 years old.
- The
Dog
class is defined. It has a constructor method (__init__
) that takesname
andage
as parameters. Inside the constructor, instance attributesname
andage
are assigned with the provided values. - An instance method named
introduce
is defined. This method uses the instance attributesname
andage
to create a string that introduces the dog's name and age. - One instance of the
Dog
class is createddog1
, with a name and an age. - The
introduce
method is called on instance (dog1
), and it generates a personalized introduction for the dog using its attributes.
Class Methods
Class methods are defined using the @classmethod
decorator. They operate on class-level data and have access to class variables and other class methods. The first parameter of a class method is always 'cls', which is a reference to the class that is calling the method.
class MyClass:
class_attribute = "This is a class attribute"
class_instances = 0
def __init__(self, instance_attribute):
self.instance_attribute = instance_attribute
MyClass.class_instances += 1
@classmethod
def class_method(cls):
print(f"Accessing class attribute: {cls.class_attribute}")
print(f"Class has run {cls.class_instances} times")
def instance_method(self):
print(f"Accessing instance attribute: {self.instance_attribute}")
# Creating an instance of MyClass
obj = MyClass("This is an instance attribute")
# Using the class method to access class attribute
obj.class_method() # or MyClass.class_method()
# Using the instance method to access instance attribute
obj.instance_method()
Accessing class attribute: This is a class attribute
Class has run 1 times
Accessing instance attribute: This is an instance attribute
- The
MyClass
class is defined with a class attributeclass_attribute
and another class attributeclass_instances
to keep track of the number of times the class has been instantiated. - The
__init__
constructor is defined. It initializes the instance with aninstance_attribute
and increments theclass_instances
class attribute to count the number of instances created. Each time an instance is created,class_instances
is incremented. - A class method
class_method
is defined using the@classmethod
decorator. This method accesses the class attributeclass_attribute
and also prints the number of times the class has been instantiated using theclass_instances
class attribute. - An instance method
instance_method
is defined. This method accesses the instance attributeinstance_attribute
. - Class and instance method is being called that print the messages.
Static Methods
Static methods are defined using the @staticmethod
decorator. They don't have access to instance-specific or class-specific data, and they behave like regular functions but are defined within a class for organization purposes.
class MathUtils:
@staticmethod
def multiply(x, y):
return x * y
@staticmethod
def square(x):
return x ** 2
# Using static methods
product = MathUtils.multiply(5, 3)
squared = MathUtils.square(4)
print(product) # Output: 15
print(squared) # Output: 16
- The
MathUtils
class is defined. It contains two static methods:multiply
andsquare
multiply
static method takes two argumentsx
andy
. Inside the method, the product ofx
andy
is calculated and the result is returned as the output of the method.square
static method takes a single argumentx
. Inside the method, the square ofx
is calculated and the result is returned as the output of the method.- The static methods are called directly on the class
MathUtils
. Themultiply
method is used to calculate the product of 5 and 3, and thesquare
method is used to calculate the square of 4.
To summarize:
- Instance methods are used for operations that need access to instance-specific data.
- Class methods are used for operations that involve class-level data and don't need access to instance-specific data.
- Static methods are used for operations that don't depend on either instance-specific or class-specific data.
Comprehensive Example
# Define a class called BankAccount
class BankAccount:
# Class variable to keep track of total accounts
total_accounts = 0
# Initializer for the class
def __init__(self, account_number, balance):
# Instance variables for account number and balance
self.account_number = account_number
self.balance = balance
# Increment total_accounts on instance creation
BankAccount.total_accounts += 1
# Instance method for deposit
def deposit(self, amount):
self.balance += amount
# Instance method for withdrawal
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
else:
print("Insufficient balance")
# Instance method to get balance
def get_balance(self):
return self.balance
# Class method to get total number of accounts
@classmethod
def get_total_accounts(cls):
return cls.total_accounts
# Static method to check if an account number is valid
@staticmethod
def is_valid_account_number(account_number):
return len(account_number) == 5
# Creating BankAccount instances
account1 = BankAccount("12345", 1000)
account2 = BankAccount("67890", 500)
# Performing transactions using instance methods
account1.deposit(200)
account1.withdraw(50)
account2.deposit(1000)
account2.withdraw(700)
# Displaying balance for accounts using instance methods
print(f"Closing balance of account 1 is ${account1.get_balance()}")
print(f"Closing balance of account 2 is ${account2.get_balance()}")
# Validating account numbers using static method
print("Is '12345' a valid account number?", BankAccount.is_valid_account_number("12345"))
print("Is '789' a valid account number?", BankAccount.is_valid_account_number("789"))
# Displaying total number of accounts using class method
print("Total accounts:", BankAccount.get_total_accounts())
Closing balance of account 1 is $1150
Closing balance of account 2 is $800
Is '12345' a valid account number? True
Is '789' a valid account number? False
Total accounts: 2
Explanation
Let's break down the code step by step and explain each part:
class BankAccount:
total_accounts = 0
- The
BankAccount
class is defined. total_accounts
is a class variable that keeps track of the total number of bank accounts created.
def __init__(self, account_number, balance):
self.account_number = account_number
self.balance = balance
BankAccount.total_accounts += 1
- The
__init__
method is the class constructor that initializes a bank account with anaccount_number
andbalance
. account_number
andbalance
are instance attributes specific to each account.BankAccount.total_accounts
is incremented every time a new account instance is created, maintaining a count of total accounts.
def deposit(self, amount):
self.balance += amount
- The
deposit
method takes anamount
parameter and increases the balance of the account by that amount.
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
else:
print("Insufficient balance")
- The
withdraw
method takes anamount
parameter and checks if the account has sufficient balance before subtracting the amount. - If the balance is insufficient, it prints an error message.
def get_balance(self):
return self.balance
- The
get_balance
method returns the current balance of the account.
@classmethod
def get_total_accounts(cls):
return cls.total_accounts
- The
get_total_accounts
class method returns the total number of bank accounts created. It's a class-level operation.
@staticmethod
def is_valid_account_number(account_number):
return len(account_number) == 5
- The
is_valid_account_number
static method takes anaccount_number
parameter and checks if it has a length of 5 characters. - It returns
True
if the account number is valid (5 characters), otherwiseFalse
.
The code continues by creating two bank account instances (account1
and account2
), performing transactions using instance methods (deposit
and withdraw
), displaying account balances, validating account numbers using the static method, and finally, displaying the total number of accounts using the class method.