Python OOP 101: Class vs Instance attributes

Photo by Kevin Ku on Unsplash

Python OOP 101: Class vs Instance attributes

In Python, the main difference between class attributes and instance attributes involves the level at which these attributes are declared and how they are accessed within the class and its instances:

  1. Class Attributes:

    • Class attributes are variables defined directly in the class and shared among all instances of the class. They are not unique to each instance.

    • If a class attribute is modified using the class name, the change is reflected across all instances, unless an instance has overridden that attribute with its own instance attribute.

    • Class attributes are used when you want to define a property that should be the same for every instance of the class.

Example:

    class Dog:
        species = "Canis familiaris"  # Class attribute

        def __init__(self, name):
            self.name = name  # Instance attribute

Here, species is a class attribute, which will be the same for all instances of Dog.

  1. Instance Attributes:

    • Instance attributes are variables specific to each instance of the class; they are defined in the constructor, typically using the self keyword, which makes each instance carry its own set of those attributes.

    • Changes to an instance attribute affect only that specific instance.

    • Instance attributes allow each object to have its own unique data.

Continuing the previous example:

    buddy = Dog("Buddy")
    daisy = Dog("Daisy")

In this case, buddy.name and daisy.name are instance attributes. Buddy's name being "Buddy" does not affect Daisy's name, which is "Daisy".

Class attributes are useful for defining constants or default values shared across all instances, whereas instance attributes are used for data specific to an individual object. This distinction helps manage memory more efficiently and keeps the behavior of objects appropriately scoped within the context of the class design.

Here's a table summarizing the key differences:

FeatureClass AttributeInstance Attribute
Definition LocationInside class definition, outside __init__()Inside __init__() function
Shared Between ObjectsYes, shared by all instancesNo, specific to each instance
Modifying ValueAffects all instancesAffects only the current instance

Example: Library Book Manager

Let's consider a simple real-world example involving a class to manage books in a library. In this scenario, class attributes are used to store information that is common to all books, such as the library name, while instance attributes store details specific to each book, like the title and author.

Code Structure:

class Book:
    # Class attribute for the library name
    library_name = "Central Library"

    def __init__(self, title, author):
        # Instance attributes for book-specific details
        self.title = title
        self.author = author

    def display_info(self):
        # Display book information and the library it belongs to
        print(f"Book: {self.title} by {self.author}")
        print(f"Available at: {self.library_name}")

# Setting the library name via the class, affecting all instances
Book.library_name = "Downtown Branch"

# Creating instances of Book
book1 = Book("1984", "George Orwell")
book2 = Book("To Kill a Mockingbird", "Harper Lee")

# Displaying information about each book
book1.display_info()
book2.display_info()

Usage and Explanation:

  • Class Attribute (library_name): This is set once and shared among all books. When the library name is changed by setting Book.library_name, it updates the information for all book instances, as they all refer to this single class-level attribute.

  • Instance Attributes (title, author): Each instance of Book (each book) has its own title and author. These attributes are specific to individual instances, so changing the title or author of one book does not affect others.

This design allows you to manage common attributes at the class level (like the library name), reducing redundancy, while still keeping individual book data isolated to each instance. Such a structure is helpful for keeping the system organized and making updates easy, especially when changes at the class level (like a change in library name or location) need to be reflected across all books without manually updating each book.

Reference:

  1. Python 3.9 docs: Classes