Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • πŸ“ Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • πŸ“ Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • πŸ“ Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • πŸ“ Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • πŸ“ While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • πŸ“ For Each Assignments
    • πŸ“ All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • πŸ“ Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • πŸ“ Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • πŸ“ Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • πŸ“ Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • πŸ“ Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • πŸ“ Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • πŸ“ Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • πŸ“ Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • πŸ“ Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • πŸ“ Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • πŸ“ Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • πŸ“ Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • πŸ“ Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • πŸ“ Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • πŸ“ Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • πŸ“ Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • πŸ“ Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • πŸ“ Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • πŸ“ Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: __slots__

Python __slots__ - Complete Guide

Save memory and speed up your Python classes with __slots__.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What is __slots__?
  • Why Use __slots__?
  • Basic Usage
  • Memory Savings
  • __slots__ and Inheritance
  • Limitations
  • Real-World Example
  • Best Practices
  • Try It Yourself
  • Quick Quiz
  • Frequently Asked Questions
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is __slots__ β€” a special attribute that saves memory and speeds up classes
  • Why use it β€” memory efficiency, performance, attribute control
  • Basic usage β€” how to define __slots__ in your classes
  • Memory savings β€” see how much memory you can save
  • Inheritance β€” how __slots__ works with inheritance
  • Limitations β€” what you can't do with __slots__

What is __slots__?

__slots__ is a special attribute in Python that lets you tell the interpreter exactly what attributes a class can have. It's like giving your class a fixed list of allowed attributes instead of letting it create them dynamically.

Think of __slots__ like a parking lot with assigned spaces. Without __slots__, you can park anywhere (any attribute). With __slots__, you have specific spots (attributes), and if you try to park somewhere else, you get turned away. This makes everything more organized and efficient.

By default, Python classes store attributes in a dictionary (__dict__). This is flexible but uses a lot of memory. __slots__ replaces this dictionary with a more efficient structure.

πŸ’‘ Key concept: __slots__ tells Python exactly what attributes to expect. This saves memory and makes attribute access faster.

Why Use __slots__?

1

The Benefits of __slots__

__slots__ gives you three main benefits:

# Why Use __slots__?

print("=" * 50)
print("WHY USE __slots__?")
print("=" * 50)

# ============================================================
# WITHOUT __slots__ β€” Flexible but Memory Heavy
# ============================================================

print("\n❌ WITHOUT __slots__:")

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 30)

# You can add ANY attribute at any time
person.city = "NYC"  # Works!
person.email = "alice@example.com"  # Works!
person.phone = "123-456-7890"  # Works!

print(f"   Person: {person.name}, {person.age}")
print(f"   City: {person.city}")
print(f"   Email: {person.email}")
print(f"   Phone: {person.phone}")

# Each object has a __dict__ that stores all attributes
print(f"   __dict__: {person.__dict__}")

print("\n   ❌ Problems:")
print("   β€’ Accidental attributes can be created")
print("   β€’ Each object has a dictionary (memory heavy)")
print("   β€’ Attribute access is slightly slower")


# ============================================================
# WITH __slots__ β€” Controlled and Efficient
# ============================================================

print("\nβœ… WITH __slots__:")

class PersonSlotted:
    __slots__ = ['name', 'age']  # Only these attributes are allowed
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

person2 = PersonSlotted("Bob", 25)
print(f"   Person: {person2.name}, {person2.age}")

# You can still access attributes normally
person2.name = "Robert"
print(f"   Updated name: {person2.name}")

# But you CANNOT add new attributes
try:
    person2.city = "LA"
except AttributeError as e:
    print(f"   ❌ {e}")

# There is NO __dict__ (saves memory)
try:
    print(f"   __dict__: {person2.__dict__}")
except AttributeError as e:
    print(f"   ❌ No __dict__: {e}")

print("\nβœ… Benefits:")
print("   β€’ Prevents accidental attribute creation")
print("   β€’ Saves memory (no __dict__ per object)")
print("   β€’ Faster attribute access")


# ============================================================
# BENEFITS SUMMARY
# ============================================================

print("\n" + "-" * 30)
print("BENEFITS OF __slots__")
print("-" * 30)
print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ BENEFIT             β”‚ WHAT IT MEANS FOR YOU                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Memory Savings      β”‚ No __dict__ per object, less memory used  β”‚
β”‚                     β”‚                                            β”‚
β”‚ Faster Access       β”‚ Attribute access is faster               β”‚
β”‚                     β”‚                                            β”‚
β”‚ Prevents Errors     β”‚ Can't accidentally create new attributes β”‚
β”‚                     β”‚                                            β”‚
β”‚ Better Performance  β”‚ 10-30% faster attribute access           β”‚
β”‚                     β”‚                                            β”‚
β”‚ Immutability        β”‚ Restricts what attributes can exist      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Œ __slots__ is perfect for classes with many objects.
""")

Benefits of __slots__:

  • Memory savings β€” no __dict__ per object
  • Faster access β€” attribute access is quicker
  • Prevents errors β€” can't accidentally create new attributes
  • Better performance β€” 10-30% faster attribute access
  • Immutability β€” restricts what attributes can exist

Quick Check: What does __slots__ do? (Answer: It tells Python exactly what attributes a class can have, saving memory and preventing accidental attribute creation)

Basic Usage

2

How to Use __slots__

Using __slots__ is very simple. Just define it as a class variable containing a list or tuple of attribute names.

# Basic __slots__ Usage

print("=" * 50)
print("BASIC __slots__ USAGE")
print("=" * 50)

# ============================================================
# DEFINING __slots__
# ============================================================

print("\n1. DEFINING __slots__")

class Student:
    # List of allowed attributes
    __slots__ = ['name', 'age', 'grade']
    
    def __init__(self, name, age, grade):
        self.name = name
        self.age = age
        self.grade = grade
    
    def get_info(self):
        return f"{self.name}, {self.age} years old, Grade: {self.grade}"

student = Student("Alice", 20, "A")
print(f"   {student.get_info()}")

# All attributes work as normal
student.name = "Bob"
student.age = 21
print(f"   Updated: {student.get_info()}")


# ============================================================
# __slots__ TUPLE VS LIST
# ============================================================

print("\n2. __slots__ TUPLE VS LIST")

# Both work, tuple is slightly more memory efficient
class UsingList:
    __slots__ = ['x', 'y']  # List works
    def __init__(self, x, y):
        self.x = x
        self.y = y

class UsingTuple:
    __slots__ = ('x', 'y')  # Tuple also works
    def __init__(self, x, y):
        self.x = x
        self.y = y

print("   Both lists and tuples work for __slots__")
print("   βœ… Tuples are slightly more memory efficient")


# ============================================================
# __slots__ WITH METHODS
# ============================================================

print("\n3. __slots__ WITH METHODS")

class Calculator:
    __slots__ = ['value']
    
    def __init__(self, value):
        self.value = value
    
    def add(self, amount):
        self.value += amount
        return self.value
    
    def multiply(self, amount):
        self.value *= amount
        return self.value
    
    def get_value(self):
        return self.value

calc = Calculator(5)
print(f"   Value: {calc.get_value()}")
print(f"   Add 3: {calc.add(3)}")
print(f"   Multiply 2: {calc.multiply(2)}")


# ============================================================
# __slots__ AND DEFAULT VALUES
# ============================================================

print("\n4. __slots__ AND DEFAULT VALUES")

class Product:
    __slots__ = ['name', 'price', 'stock']
    
    def __init__(self, name, price, stock=0):
        self.name = name
        self.price = price
        self.stock = stock  # Default values work fine

product1 = Product("Laptop", 999.99, 10)
product2 = Product("Mouse", 29.99)  # Uses default stock

print(f"   Product 1: {product1.name}, ${product1.price}, Stock: {product1.stock}")
print(f"   Product 2: {product2.name}, ${product2.price}, Stock: {product2.stock}")


# ============================================================
# __slots__ WITH @property
# ============================================================

print("\n5. __slots__ WITH @property")

class Temperature:
    __slots__ = ['_celsius']
    
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Temperature below absolute zero")
        self._celsius = value
    
    @property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32

temp = Temperature(25)
print(f"   Celsius: {temp.celsius}Β°C")
print(f"   Fahrenheit: {temp.fahrenheit}Β°F")

temp.celsius = 30
print(f"   After update - Celsius: {temp.celsius}Β°C")


# ============================================================
# KEY RULES
# ============================================================

print("\n" + "-" * 30)
print("KEY RULES FOR __slots__")
print("-" * 30)
print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ RULES                                                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 1. Define __slots__ as a list or tuple of attribute names         β”‚
β”‚ 2. You can only assign attributes that are in __slots__           β”‚
β”‚ 3. Classes with __slots__ don't have a __dict__                   β”‚
β”‚ 4. __slots__ works with @property and methods                     β”‚
β”‚ 5. Default values work fine in __init__                           β”‚
β”‚ 6. Use tuple for slightly better memory efficiency                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
""")

Basic usage key points:

  • __slots__ = ['name', 'age'] β€” defines allowed attributes
  • List or tuple β€” both work, tuple is slightly better
  • Methods work β€” you can have methods too
  • Default values β€” work as expected in __init__
  • @property β€” works perfectly with __slots__

Quick Check: How do you define __slots__ in a class? (Answer: Add __slots__ = ['attribute1', 'attribute2'] as a class variable)

Memory Savings

3

How Much Memory You Can Save

The main reason to use __slots__ is memory savings. Let's see how much difference it makes.

# Memory Savings with __slots__

print("=" * 50)
print("MEMORY SAVINGS WITH __slots__")
print("=" * 50)

import sys

# ============================================================
# CLASS WITHOUT __slots__
# ============================================================

print("\n1. CLASS WITHOUT __slots__")

class WithoutSlots:
    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

# Create 1000 objects without __slots__
objects_without = [WithoutSlots(i, i*2, i*3, i*4) for i in range(1000)]

# Memory usage (approximate)
memory_without = sys.getsizeof(objects_without[0]) * 1000
print(f"   Memory for 1000 objects: ~{memory_without:,} bytes")
print(f"   Each object has __dict__: {objects_without[0].__dict__}")


# ============================================================
# CLASS WITH __slots__
# ============================================================

print("\n2. CLASS WITH __slots__")

class WithSlots:
    __slots__ = ['a', 'b', 'c', 'd']
    
    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

# Create 1000 objects with __slots__
objects_with = [WithSlots(i, i*2, i*3, i*4) for i in range(1000)]

# Memory usage (approximate)
memory_with = sys.getsizeof(objects_with[0]) * 1000
print(f"   Memory for 1000 objects: ~{memory_with:,} bytes")

# No __dict__!
try:
    print(f"   __dict__: {objects_with[0].__dict__}")
except AttributeError:
    print("   βœ… No __dict__ (memory saved)")


# ============================================================
# COMPARISON
# ============================================================

print("\n3. COMPARISON")

print(f"   Without __slots__: ~{memory_without:,} bytes")
print(f"   With __slots__:    ~{memory_with:,} bytes")
print(f"   Memory saved:     ~{memory_without - memory_with:,} bytes")
print(f"   Savings:          ~{(1 - memory_with/memory_without) * 100:.1f}%")

print("\n   βœ… With 1000 objects, __slots__ saves significant memory")
print("   βœ… For large-scale applications, this is huge")


# ============================================================
# REAL-WORLD EXAMPLE - 1 MILLION OBJECTS
# ============================================================

print("\n4. REAL-WORLD SCENARIO - 1 MILLION OBJECTS")

# Approximate memory usage for 1,000,000 objects
million_without = memory_without * 1000  # 1,000 objects * 1000 = 1,000,000
million_with = memory_with * 1000

print(f"   Without __slots__: ~{million_without:,} bytes (~{million_without // 1024 // 1024} MB)")
print(f"   With __slots__:    ~{million_with:,} bytes (~{million_with // 1024 // 1024} MB)")
print(f"   Memory saved:     ~{(million_without - million_with) // 1024 // 1024} MB")

print("\n   πŸ’‘ For large datasets, __slots__ is a game-changer!")


# ============================================================
# WHY MEMORY IS SAVED
# ============================================================

print("\n" + "-" * 30)
print("WHY MEMORY IS SAVED")
print("-" * 30)
print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ WITHOUT __slots__   β”‚   WITH __slots__                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Each object has a   β”‚   Each object has a fixed structure         β”‚
β”‚ dictionary (__dict__)β”‚   (no dictionary)                          β”‚
β”‚                     β”‚                                             β”‚
β”‚ Dict is flexible    β”‚   Structure is compact and efficient        β”‚
β”‚ but memory heavy    β”‚                                             β”‚
β”‚                     β”‚                                             β”‚
β”‚ ~50-60% more memory β”‚   Uses less memory                          β”‚
β”‚                     β”‚                                             β”‚
β”‚ Good for flexibilityβ”‚   Good for performance & memory             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Œ __slots__ replaces a dictionary with a fixed array.
""")

Memory savings key points:

  • No __dict__ β€” saves about 50-60% memory
  • Fixed structure β€” more compact than dictionary
  • Scales well β€” even better with many objects
  • Real impact β€” 1 million objects can save 40-60 MB

Quick Check: What's the main reason to use __slots__? (Answer: To save memory by eliminating the __dict__ from each object)

__slots__ and Inheritance

4

How __slots__ Works with Inheritance

__slots__ works differently with inheritance. The child class's __slots__ are combined with the parent's.

# __slots__ and Inheritance

print("=" * 50)
print("__slots__ AND INHERITANCE")
print("=" * 50)

# ============================================================
# PARENT WITH __slots__
# ============================================================

print("\n1. PARENT WITH __slots__")

class Animal:
    __slots__ = ['name', 'species']
    
    def __init__(self, name, species):
        self.name = name
        self.species = species

animal = Animal("Rex", "Dog")
print(f"   Animal: {animal.name} ({animal.species})")


# ============================================================
# CHILD WITH __slots__ (Inherits and adds more)
# ============================================================

print("\n2. CHILD WITH __slots__")

class Dog(Animal):
    __slots__ = ['breed', 'age']  # Adds more attributes
    
    def __init__(self, name, species, breed, age):
        super().__init__(name, species)
        self.breed = breed
        self.age = age

dog = Dog("Rex", "Canine", "German Shepherd", 3)
print(f"   Dog: {dog.name}, {dog.species}, {dog.breed}, {dog.age}")


# ============================================================
# CHILD WITHOUT __slots__ (Gets __dict__)
# ============================================================

print("\n3. CHILD WITHOUT __slots__")

class Cat(Animal):
    # No __slots__ defined
    def __init__(self, name, species, color):
        super().__init__(name, species)
        self.color = color

cat = Cat("Whiskers", "Feline", "Orange")
print(f"   Cat: {cat.name}, {cat.species}, {cat.color}")

# Cat has __dict__ because it doesn't define __slots__
print(f"   Cat __dict__: {cat.__dict__}")

# Can add new attributes (because of __dict__)
cat.toys = ["ball", "mouse"]
print(f"   Cat toys: {cat.toys}")


# ============================================================
# CHILD WITH __slots__ AND PARENT WITHOUT
# ============================================================

print("\n4. CHILD WITH __slots__, PARENT WITHOUT")

class Vehicle:
    def __init__(self, brand):
        self.brand = brand

class Car(Vehicle):
    __slots__ = ['model', 'year']  # Child has __slots__
    
    def __init__(self, brand, model, year):
        super().__init__(brand)
        self.model = model
        self.year = year

car = Car("Toyota", "Camry", 2023)
print(f"   Car: {car.brand}, {car.model}, {car.year}")

# Parent doesn't have __slots__, so car has __dict__
print(f"   Car __dict__: {car.__dict__}")


# ============================================================
# RULES SUMMARY
# ============================================================

print("\n" + "-" * 30)
print("INHERITANCE RULES")
print("-" * 30)
print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SCENARIO                    β”‚ RESULT                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Parent has __slots__        β”‚ Child's __slots__ extends parent's        β”‚
β”‚ Child has __slots__         β”‚ Both sets of attributes are allowed       β”‚
β”‚                             β”‚                                            β”‚
β”‚ Parent has __slots__        β”‚ Child gets a __dict__ (no memory savings) β”‚
β”‚ Child has NO __slots__      β”‚                                            β”‚
β”‚                             β”‚                                            β”‚
β”‚ Parent has NO __slots__     β”‚ Child can use __slots__                   β”‚
β”‚ Child has __slots__         β”‚ Parent still has __dict__                 β”‚
β”‚                             β”‚                                            β”‚
β”‚ Both have __slots__         β”‚ Both are memory efficient                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Œ For full memory savings, use __slots__ in both parent and child.
""")

Inheritance key points:

  • Parent has __slots__ β€” child can extend them
  • Parent has __slots__, child doesn't β€” child gets __dict__
  • Parent doesn't have __slots__, child does β€” child has __slots__, parent still has __dict__
  • Both have __slots__ β€” full memory savings

Quick Check: What happens if a child class doesn't define __slots__ but the parent does? (Answer: The child gets a __dict__, losing the memory savings)

Limitations

5

What You Can't Do With __slots__

__slots__ is great, but it has some limitations you should know about.

# Limitations of __slots__

print("=" * 50)
print("LIMITATIONS OF __slots__")
print("=" * 50)

# ============================================================
# 1. CAN'T ADD ATTRIBUTES NOT IN __slots__
# ============================================================

print("\n1. CAN'T ADD ATTRIBUTES")

class User:
    __slots__ = ['name', 'email']
    
    def __init__(self, name, email):
        self.name = name
        self.email = email

user = User("Alice", "alice@example.com")

# This works
user.name = "Bob"

# This fails
try:
    user.age = 30
except AttributeError as e:
    print(f"   ❌ Can't add age: {e}")

print("   ⚠️ You're limited to the attributes you define in __slots__")


# ============================================================
# 2. CAN'T USE __dict__ (unless added to __slots__)
# ============================================================

print("\n2. CAN'T USE __dict__")

class Point:
    __slots__ = ['x', 'y']
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(1, 2)

try:
    print(f"   __dict__: {p.__dict__}")
except AttributeError as e:
    print(f"   ❌ No __dict__: {e}")

print("   ⚠️ You can add '__dict__' to __slots__ if you need it")
print("   __slots__ = ['x', 'y', '__dict__']  # But this defeats the purpose")


# ============================================================
# 3. CAN'T USE __weakref__ (unless added)
# ============================================================

print("\n3. CAN'T USE __weakref__")

class Data:
    __slots__ = ['value']
    
    def __init__(self, value):
        self.value = value

d = Data(10)

try:
    import weakref
    wr = weakref.ref(d)
except TypeError as e:
    print(f"   ❌ Weakref not supported: {e}")

print("   ⚠️ Add '__weakref__' to __slots__ if you need weakrefs")


# ============================================================
# 4. CAN'T USE DEFAULT VALUES IN __slots__ DEFINITION
# ============================================================

print("\n4. CAN'T USE DEFAULT VALUES IN __slots__ DEFINITION")

# ❌ This is wrong
# class Bad:
#     __slots__ = ['name', 'age']  # You CAN'T put default values here
#     name = "default"  # This would be a class variable, not an instance attribute

# βœ… This is correct
class Good:
    __slots__ = ['name', 'age']
    
    def __init__(self, name="default", age=0):  # Defaults go in __init__
        self.name = name
        self.age = age

g = Good()
print(f"   Good default: {g.name}, {g.age}")

print("   βœ… Put default values in __init__, not in __slots__")


# ============================================================
# 5. CAN'T USE __slots__ WITH __dict__ IN SUBCLASSES
# ============================================================

print("\n5. CAN'T USE __slots__ WITH __dict__ IN SUBCLASSES")

class Parent:
    __slots__ = ['name']

class Child(Parent):
    __slots__ = ['age']  # This works

try:
    class BadChild(Parent):
        __slots__ = ['age', '__dict__']  # This can cause issues
except Exception as e:
    print(f"   ❌ Potential issue: {e}")

print("   ⚠️ Mixing __slots__ and __dict__ in inheritance can be tricky")


# ============================================================
# SUMMARY
# ============================================================

print("\n" + "-" * 30)
print("LIMITATIONS SUMMARY")
print("-" * 30)
print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LIMITATION                  β”‚ WORKAROUND                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Can't add new attributes    β”‚ Plan your attributes carefully           β”‚
β”‚                             β”‚                                            β”‚
β”‚ No __dict__ by default      β”‚ Add '__dict__' to __slots__ (if needed)  β”‚
β”‚                             β”‚                                            β”‚
β”‚ No __weakref__ by default   β”‚ Add '__weakref__' to __slots__           β”‚
β”‚                             β”‚                                            β”‚
β”‚ No defaults in __slots__    β”‚ Use __init__ for defaults                β”‚
β”‚                             β”‚                                            β”‚
β”‚ Complex inheritance issues  β”‚ Keep inheritance simple                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Œ Know the limitations, use __slots__ when it makes sense.
""")

Limitations key points:

  • No new attributes β€” can't add attributes not in __slots__
  • No __dict__ β€” by default, but you can add it
  • No __weakref__ β€” by default, but you can add it
  • No defaults β€” put default values in __init__
  • Inheritance complexity β€” can get tricky with __dict__

Quick Check: Can you add new attributes to an object created from a class with __slots__? (Answer: No β€” you can only use attributes defined in __slots__)

Real-World Example

6

Building a Data Processing System

# Real-World Example: Data Processing System

import sys
import random
from time import time

print("=" * 60)
print("DATA PROCESSING SYSTEM")
print("=" * 60)

# ============================================================
# DATA CLASS WITH __slots__ (Memory Efficient)
# ============================================================

class DataRecord:
    """Memory-efficient data record using __slots__"""
    
    __slots__ = ['id', 'name', 'value', 'timestamp', 'active']
    
    def __init__(self, id, name, value, timestamp, active=True):
        self.id = id
        self.name = name
        self.value = value
        self.timestamp = timestamp
        self.active = active
    
    def process(self):
        """Process the record"""
        if self.active:
            return self.value * 2
        return 0
    
    def get_summary(self):
        return f"ID: {self.id}, Name: {self.name}, Value: {self.value}"


# ============================================================
# DATA CLASS WITHOUT __slots__ (For Comparison)
# ============================================================

class DataRecordWithout:
    """Regular class without __slots__"""
    
    def __init__(self, id, name, value, timestamp, active=True):
        self.id = id
        self.name = name
        self.value = value
        self.timestamp = timestamp
        self.active = active
    
    def process(self):
        if self.active:
            return self.value * 2
        return 0


# ============================================================
# DATA PROCESSOR
# ============================================================

class DataProcessor:
    """Process data records efficiently"""
    
    def __init__(self, use_slots=True):
        self.use_slots = use_slots
        self.records = []
    
    def generate_data(self, count):
        """Generate random data records"""
        self.records = []
        for i in range(count):
            if self.use_slots:
                record = DataRecord(
                    i,
                    f"Record_{i}",
                    random.random() * 100,
                    time(),
                    active=random.random() > 0.2
                )
            else:
                record = DataRecordWithout(
                    i,
                    f"Record_{i}",
                    random.random() * 100,
                    time(),
                    active=random.random() > 0.2
                )
            self.records.append(record)
    
    def process_all(self):
        """Process all records"""
        results = []
        for record in self.records:
            results.append(record.process())
        return results
    
    def get_summary(self):
        """Get summary of records"""
        active = sum(1 for r in self.records if r.active)
        total = len(self.records)
        return {
            "total": total,
            "active": active,
            "inactive": total - active,
            "average_value": sum(r.value for r in self.records) / total if total > 0 else 0
        }


# ============================================================
# DEMONSTRATION
# ============================================================

print("\n1. CREATING DATA RECORDS")

# With __slots__
processor_slots = DataProcessor(use_slots=True)
processor_slots.generate_data(10)

print("   Records with __slots__:")
for i, record in enumerate(processor_slots.records[:3]):
    print(f"      {record.get_summary()}")
print("      ...")

print("\n2. MEMORY COMPARISON")

# Create 10,000 records
count = 10000
processor_slots = DataProcessor(use_slots=True)
processor_slots.generate_data(count)

processor_without = DataProcessor(use_slots=False)
processor_without.generate_data(count)

# Memory usage
mem_slots = sys.getsizeof(processor_slots.records[0]) * count
mem_without = sys.getsizeof(processor_without.records[0]) * count

print(f"   Records: {count:,}")
print(f"   With __slots__: {mem_slots:,} bytes")
print(f"   Without __slots__: {mem_without:,} bytes")
print(f"   Memory saved: {mem_without - mem_slots:,} bytes ({((mem_without - mem_slots) / mem_without * 100):.1f}%)")

print("\n3. PERFORMANCE TEST")

import time

# Test with __slots__
processor_slots = DataProcessor(use_slots=True)
processor_slots.generate_data(10000)
start = time.time()
processor_slots.process_all()
time_slots = time.time() - start

# Test without __slots__
processor_without = DataProcessor(use_slots=False)
processor_without.generate_data(10000)
start = time.time()
processor_without.process_all()
time_without = time.time() - start

print(f"   With __slots__: {time_slots:.4f}s")
print(f"   Without __slots__: {time_without:.4f}s")
print(f"   Speed improvement: {((time_without - time_slots) / time_without * 100):.1f}%")

print("\n4. PROCESSING SUMMARY")
summary = processor_slots.get_summary()
print(f"   Total records: {summary['total']:,}")
print(f"   Active records: {summary['active']:,}")
print(f"   Inactive records: {summary['inactive']:,}")
print(f"   Average value: {summary['average_value']:.2f}")

print("\n" + "=" * 60)
print("KEY TAKEAWAYS:")
print("=" * 60)
print("βœ… __slots__ saves memory (40-60% reduction)")
print("βœ… __slots__ improves performance (10-30% faster)")
print("βœ… __slots__ prevents accidental attribute creation")
print("βœ… Use __slots__ for classes with many instances")
print("βœ… Data processing is a perfect use case for __slots__")

Real-world example key points:

  • DataRecord β€” memory-efficient class with __slots__
  • Memory savings β€” 40-60% less memory
  • Speed improvement β€” 10-30% faster
  • Data processing β€” perfect use case for __slots__
  • Scale β€” even better with more objects

Quick Check: When should you use __slots__? (Answer: When you have many instances of a class and memory matters, like in data processing)

Best Practices

7

Using __slots__ Effectively

# Best Practices for __slots__

print("=" * 60)
print("BEST PRACTICES FOR __slots__")
print("=" * 60)

# ============================================================
# 1. USE __slots__ FOR CLASSES WITH MANY INSTANCES
# ============================================================

print("\n1. USE __slots__ FOR MANY INSTANCES")

# βœ… GOOD: For data classes with many instances
class Point:
    __slots__ = ['x', 'y', 'z']
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

# ❌ BAD: For classes with few instances
class Config:
    # Few instances, __slots__ won't save much memory
    def __init__(self, setting1, setting2):
        self.setting1 = setting1
        self.setting2 = setting2

print("   βœ… Use __slots__ when you have many objects")


# ============================================================
# 2. USE TUPLES FOR __slots__ (Memory Efficient)
# ============================================================

print("\n2. USE TUPLES FOR __slots__")

# βœ… GOOD: Use tuple (slightly more memory efficient)
class Good:
    __slots__ = ('name', 'age', 'city')
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

# ❌ BAD: Using list (works but uses slightly more memory)
class Bad:
    __slots__ = ['name', 'age', 'city']  # Works but less efficient
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

print("   βœ… Use tuple for __slots__ for better memory efficiency")


# ============================================================
# 3. DON'T MIX __slots__ AND __dict__ UNLESS NECESSARY
# ============================================================

print("\n3. DON'T MIX __slots__ AND __dict__")

# ❌ BAD: Adding __dict__ defeats the purpose
class BadMix:
    __slots__ = ['name', 'age', '__dict__']  # Defeats memory savings
    def __init__(self, name, age):
        self.name = name
        self.age = age

# βœ… GOOD: Keep it clean
class GoodClean:
    __slots__ = ['name', 'age']
    def __init__(self, name, age):
        self.name = name
        self.age = age

print("   βœ… Don't add __dict__ to __slots__ unless you really need it")


# ============================================================
# 4. USE __slots__ IN BOTH PARENT AND CHILD
# ============================================================

print("\n4. USE __slots__ IN BOTH PARENT AND CHILD")

# βœ… GOOD: Both have __slots__
class Parent:
    __slots__ = ['name']
    def __init__(self, name):
        self.name = name

class Child(Parent):
    __slots__ = ['age']  # Child extends parent's slots
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age

# ❌ BAD: Child missing __slots__ loses memory savings
class BadParent:
    __slots__ = ['name']
    def __init__(self, name):
        self.name = name

class BadChild(BadParent):
    # No __slots__ β€” child gets __dict__
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age

print("   βœ… Use __slots__ in both parent and child for full savings")


# ============================================================
# 5. USE __slots__ FOR IMMUTABLE DATA CLASSES
# ============================================================

print("\n5. USE __slots__ FOR IMMUTABLE DATA")

from dataclasses import dataclass

# βœ… GOOD: dataclass with frozen=True often uses __slots__ internally
@dataclass(frozen=True)
class ImmutablePoint:
    x: int
    y: int

# βœ… GOOD: Manual slots for immutability
class ManualImmutable:
    __slots__ = ['_x', '_y']
    def __init__(self, x, y):
        object.__setattr__(self, '_x', x)
        object.__setattr__(self, '_y', y)
    
    @property
    def x(self):
        return self._x
    
    @property
    def y(self):
        return self._y

print("   βœ… __slots__ is great for immutable data classes")


# ============================================================
# 6. SUMMARY
# ============================================================

print("\n" + "=" * 60)
print("BEST PRACTICES SUMMARY")
print("=" * 60)
print("""
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PRACTICE                    β”‚ WHY IT MATTERS                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Use for many instances      β”‚ Memory savings are significant            β”‚
β”‚                             β”‚                                             β”‚
β”‚ Use tuple for __slots__     β”‚ Slightly more memory efficient            β”‚
β”‚                             β”‚                                             β”‚
β”‚ Don't add __dict__          β”‚ Defeats the purpose of __slots__          β”‚
β”‚                             β”‚                                             β”‚
β”‚ Use in parent and child     β”‚ Full memory savings                       β”‚
β”‚                             β”‚                                             β”‚
β”‚ Use for immutable data      β”‚ Combines immutability with efficiency     β”‚
β”‚                             β”‚                                             β”‚
β”‚ Use when attributes are     β”‚ Prevents accidental attribute creation    β”‚
β”‚ known in advance            β”‚                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Œ __slots__ is a powerful tool, but use it when it makes sense!
""")

Best practices summary:

  • Use for many instances β€” memory savings are significant
  • Use tuple β€” slightly more memory efficient
  • Don't add __dict__ β€” defeats the purpose
  • Use in parent and child β€” full memory savings
  • Use for immutable data β€” combines immutability with efficiency
  • Use when attributes are known β€” prevents accidental creation

Quick Check: When should you avoid using __slots__? (Answer: When you need dynamic attributes or when you only have a few instances)

Try It Yourself

Experiment with __slots__ in the editor below.

Loading Pyodide... 0%
Python Code Editor
==================================================
__slots__ - PRACTICE
==================================================

1. BASIC __slots__ CLASS
Book: Python Programming by Alice Smith (2023)
❌ Can't add pages: 'Book' object has no attribute 'pages'

2. COMPARE WITH REGULAR CLASS
RegularBook __dict__: {'title': 'Python', 'author': 'Alice', 'year': 2023}
βœ… SlottedBook has no __dict__
RegularBook size: 56 bytes
SlottedBook size: 48 bytes

3. INHERITANCE WITH __slots__
Employee: Alice, ID: E001
❌ Can't add department: 'Employee' object has no attribute 'department'
πŸ†

You've Got It!

You now understand __slots__ in Python. You know how to save memory, prevent accidental attribute creation, and make your classes more efficient.

Quick Quiz

Test what you've learned:

1. What is __slots__ used for in Python?
2. What happens if you try to add an attribute not in __slots__?
3. Which is more memory efficient for __slots__?
4. Does a class with __slots__ have a __dict__?
5. When should you use __slots__?

Frequently Asked Questions

What is __slots__ in Python? β–Ό

__slots__ is a special attribute that defines the exact attributes a class can have. It saves memory by eliminating the __dict__ from each object and prevents accidental attribute creation.

How much memory does __slots__ save? β–Ό

__slots__ can save 40-60% of memory per object. The exact amount depends on the number of attributes and the size of the __dict__. For classes with many instances, the savings are significant.

Can I use __slots__ with dataclasses? β–Ό

Yes! In Python 3.10+, you can use @dataclass(slots=True) to automatically use __slots__. For older versions, you can manually add __slots__ to a dataclass.

Does __slots__ affect inheritance? β–Ό

Yes. If a parent class has __slots__, the child can extend them with its own __slots__. If the child doesn't define __slots__, it gets a __dict__ and loses the memory savings.

Can I add __dict__ to __slots__? β–Ό

Yes, you can add '__dict__' to __slots__ to allow dynamic attributes. However, this defeats the memory savings of __slots__. It's better to avoid this unless you really need it.

Should I use __slots__ for all my classes? β–Ό

No. Use __slots__ when you have many instances and memory matters. For classes with few instances, or where you need dynamic attributes, it's better to skip __slots__.

Where to Go From Here

Now that you understand __slots__ in Python, check out these related topics:

Dataclasses

Learn how dataclasses can use __slots__ for memory efficiency.

Learn More β†’

Property Decorator

Learn how @property works with __slots__.

Learn More β†’

Enums

Learn about Enums β€” another way to create efficient classes.

Learn More β†’
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Property Decorator Next: Enums β†’