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 = ageClass 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
Dogclass is defined. It has a constructor method (__init__) that takesnameandageas parameters. Inside the constructor, instance attributesnameandageare assigned with the provided values. - An instance method named
introduceis defined. This method uses the instance attributesnameandageto create a string that introduces the dog's name and age. - One instance of the
Dogclass is createddog1, with a name and an age. - The
introducemethod 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
MyClassclass is defined with a class attributeclass_attributeand another class attributeclass_instancesto keep track of the number of times the class has been instantiated. - The
__init__constructor is defined. It initializes the instance with aninstance_attributeand increments theclass_instancesclass attribute to count the number of instances created. Each time an instance is created,class_instancesis incremented. - A class method
class_methodis defined using the@classmethoddecorator. This method accesses the class attributeclass_attributeand also prints the number of times the class has been instantiated using theclass_instancesclass attribute. - An instance method
instance_methodis 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
MathUtilsclass is defined. It contains two static methods:multiplyandsquare multiplystatic method takes two argumentsxandy. Inside the method, the product ofxandyis calculated and the result is returned as the output of the method.squarestatic method takes a single argumentx. Inside the method, the square ofxis calculated and the result is returned as the output of the method.- The static methods are called directly on the class
MathUtils. Themultiplymethod is used to calculate the product of 5 and 3, and thesquaremethod 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: 2Explanation
Let's break down the code step by step and explain each part:
class BankAccount:
total_accounts = 0 - The
BankAccountclass is defined. total_accountsis 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_numberandbalance. account_numberandbalanceare instance attributes specific to each account.BankAccount.total_accountsis incremented every time a new account instance is created, maintaining a count of total accounts.
def deposit(self, amount):
self.balance += amount- The
depositmethod takes anamountparameter 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
withdrawmethod takes anamountparameter 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_balancemethod returns the current balance of the account.
@classmethod
def get_total_accounts(cls):
return cls.total_accounts- The
get_total_accountsclass 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_numberstatic method takes anaccount_numberparameter and checks if it has a length of 5 characters. - It returns
Trueif 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.