__slots__ does not (significantly) speed up attribute access:

>>> class Foo(object):
...     __slots__ = ('spam',)
...     def __init__(self):
...         self.spam = 'eggs'
... 
>>> class Bar(object):
...     def __init__(self):
...         self.spam = 'eggs'
... 
>>> import timeit
>>> timeit.timeit('t.spam', 'from __main__ import Foo; t=Foo()')
0.07030296325683594
>>> timeit.timeit('t.spam', 'from __main__ import Bar; t=Bar()')
0.07646608352661133

The goal of using __slots__ is to save memory; instead of using a .__dict__ mapping on the instance, the class has descriptors objects for each and every attribute named in __slots__ and instances have the attribute assigned wether or not they have an actual value:

>>> class Foo(object):
...     __slots__ = ('spam',)
... 
>>> dir(Foo())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'spam']
>>> Foo().spam
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: spam
>>> Foo.spam
<member 'spam' of 'Foo' objects>
>>> type(Foo.spam)
<type 'member_descriptor'>

So python still has to look at the class for each attribute access on an instance of Foo (to find the descriptor). Any unknown attribute (say, Foo.ham) will still result in Python looking through the class MRO to search for that attribute, and that includes dictionary searches. And you can still assign additional attributes to the class:

>>> Foo.ham = 'eggs'
>>> dir(Foo)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'ham', 'spam']
>>> Foo().ham
'eggs'

The slot descriptors are created when the class is created, and access memory assigned to each instance to store and retrieve a reference to the associated value (the same chunk of memory that tracks instance reference counts and a reference back to the class object). Without slots, a descriptor for __dict__ is used accessing a reference to a dict object in the same manner.

Answer from Martijn Pieters on Stack Overflow
Top answer
1 of 2
23

__slots__ does not (significantly) speed up attribute access:

>>> class Foo(object):
...     __slots__ = ('spam',)
...     def __init__(self):
...         self.spam = 'eggs'
... 
>>> class Bar(object):
...     def __init__(self):
...         self.spam = 'eggs'
... 
>>> import timeit
>>> timeit.timeit('t.spam', 'from __main__ import Foo; t=Foo()')
0.07030296325683594
>>> timeit.timeit('t.spam', 'from __main__ import Bar; t=Bar()')
0.07646608352661133

The goal of using __slots__ is to save memory; instead of using a .__dict__ mapping on the instance, the class has descriptors objects for each and every attribute named in __slots__ and instances have the attribute assigned wether or not they have an actual value:

>>> class Foo(object):
...     __slots__ = ('spam',)
... 
>>> dir(Foo())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'spam']
>>> Foo().spam
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: spam
>>> Foo.spam
<member 'spam' of 'Foo' objects>
>>> type(Foo.spam)
<type 'member_descriptor'>

So python still has to look at the class for each attribute access on an instance of Foo (to find the descriptor). Any unknown attribute (say, Foo.ham) will still result in Python looking through the class MRO to search for that attribute, and that includes dictionary searches. And you can still assign additional attributes to the class:

>>> Foo.ham = 'eggs'
>>> dir(Foo)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'ham', 'spam']
>>> Foo().ham
'eggs'

The slot descriptors are created when the class is created, and access memory assigned to each instance to store and retrieve a reference to the associated value (the same chunk of memory that tracks instance reference counts and a reference back to the class object). Without slots, a descriptor for __dict__ is used accessing a reference to a dict object in the same manner.

2 of 2
8

It might speed up a program where you instantiate lots of objects of the same class, genuinely never change what attributes they have, and cache misses on all those duplicate dictionaries present a real performance problem.

This is really just a special case of the general situation where saving space sometimes saves time as well, where cache is the limiting factor.

So, it probably won't make accessing one object faster, but may speed up accessing many objects of the same type.

See also this question.

🌐
Python
wiki.python.org › moin › UsingSlots
UsingSlots - Python Wiki
The short answer is slots are more efficient in terms of memory space and speed of access, and a bit safer than the default Python method of data access. By default, when Python creates a new instance of a class, it creates a __dict__ attribute for the class.
Discussions

python - Usage of __slots__? - Stack Overflow
Some other introspection features of python may also be adversely affected. ... I demonstrate pickling a slotted object in my answer and also address the first part of your answer. 2016-05-02T15:08:59.627Z+00:00 ... I see your point, but slots offer faster attribute access as well (as others have stated). In that case you don't need "to instantiate a lot (hundreds, thousands) of objects of the same class" in order to gain performance... More on stackoverflow.com
🌐 stackoverflow.com
What is the purpose of __slots__ in Python?
Some Python features, like multiple inheritance and certain metaprogramming techniques, may not work seamlessly with __slots__. ... When creating large numbers of instances where memory usage is a concern, such as in data processing or simulations. ... When attribute access speed is a bottleneck and slight performance ... More on designgurus.io
🌐 designgurus.io
1
10
November 23, 2024
When should I use __slots__ in a Python class, and what are the tradeoffs?
Also worth noting: if you’re using dataclasses, you’ll need to explicitly enable slots via @DataClass(slots=True) (available in Python 3.10+). In general, slots makes sense in performance-critical systems, like compilers, interpreters, or memory-heavy data processing pipelines, but for ... More on github.com
🌐 github.com
4
3
July 30, 2025
Slots for class objects? (i.e. avoiding creating __dict__ for classes themselves)
Hi there, I am working on a data-oriented library that uses classes much like any other object instance, and can generate large numbers (tens of thousands, if not low hundreds of thousands) of classes at runtime, by calling the invoking (i.e. effectively by invoking the 3-arg form of type()). ... More on discuss.python.org
🌐 discuss.python.org
0
0
November 21, 2022
🌐
DEV Community
dev.to › conradylx › leveraging-slots-for-better-performance-in-python-classes-2ol4
Leveraging __slots__ for Better Performance in Python Classes - DEV Community
August 25, 2024 - By defining slots, you tell Python to use a more efficient and compact structure for storing attributes, which helps save memory. This is especially handy when memory usage is a concern or when you need to optimize performance.
🌐
KDnuggets
kdnuggets.com › what-does-pythons-__slots__-actually-do
What Does Python’s __slots__ Actually Do? - KDnuggets
July 18, 2025 - This allows you to add, change, or delete them, but it also comes at a cost: extra memory and slower attribute access. The __slots__ declaration tells Python that these are the only attributes this object will ever need.
🌐
Medium
medium.com › @stephenjayakar › a-quick-dive-into-pythons-slots-72cdc2d334e
A quick dive into Python’s “__slots__” | by Stephen Jayakar | Medium
December 27, 2018 - As using __slots__ knows what attributes can exist for a given instance, it can allocate for the descriptors associated with an instance (instead of having to add a __dict__ for each new object). In Python, it’s a bit difficult to profile the exact amount of memory used by an instance of an object: sys.getsizeof only works well for primitives and built-ins.
🌐
Towards Data Science
towardsdatascience.com › home › latest › should you use slots? how slots affect your class, and when and how to use them
Should You Use Slots? How Slots Affect Your Class, and When and How to Use Them | Towards Data Science
March 5, 2025 - SIZE: slots eliminate the need for Python to create the dynamic dictionary but instead relies on a smaller, fixed-size array, which indirectly speeds up your app by decreasing demand on garbage collection for example.
Top answer
1 of 14
1890

TLDR

The special attribute __slots__ allows you to explicitly state which instance attributes you expect your object instances to have, with the expected results:

  1. faster attribute access.
  2. space savings in memory.

The space savings is from:

  1. Storing value references in slots instead of __dict__.
  2. Denying __dict__ and __weakref__ creation if parent classes deny them and you declare __slots__. This has the effect of denying the creation of non-slotted attributes on its instances, including within the class body (such as in methods like __init__).

Quick Caveats

Small caveat, you should only declare a particular slot one time in an inheritance tree. For example:

Copyclass Base:
    __slots__ = 'foo', 'bar'

class Right(Base):
    __slots__ = 'baz', 

class Wrong(Base):
    __slots__ = 'foo', 'bar', 'baz' # redundant foo and bar

Python doesn't object when you get this wrong (it probably should), and problems might not otherwise manifest, but your objects will take up more space than they should. Python 3.8:

Copy>>> from sys import getsizeof
>>> getsizeof(Right()), getsizeof(Wrong())
(56, 72)

This is because Base's slot descriptor has a slot separate from Wrong's. This shouldn't usually come up, but it could:

Copy>>> w = Wrong()
>>> w.foo = 'foo'
>>> Base.foo.__get__(w)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: foo
>>> Wrong.foo.__get__(w)
'foo'

The biggest caveat is for multiple inheritance - multiple "parent classes with nonempty slots" cannot be combined.

To accommodate this restriction, follow best practices: create abstractions with empty __slots__ for every parent class (or for every parent class but one), then inherit from these abstractions instead of their concrete versions in your new concrete class. (The original parent classes should also inherit from their respective abstractions, of course.)

See section on multiple inheritance below for an example.

Requirements

  • To have attributes named in __slots__ to actually be stored in slots instead of a __dict__, a class must inherit from object (automatic in Python 3, but must be explicit in Python 2).

  • To prevent the creation of a __dict__, you must inherit from object and all classes in the inheritance must declare __slots__ and none of them can have a '__dict__' entry.

There are a lot of details if you wish to keep reading.

Why use __slots__

Faster attribute access

The creator of Python, Guido van Rossum, states that he actually created __slots__ for faster attribute access.

It's trivial to demonstrate measurably significant speedup:

Copyimport timeit

class Foo(object): __slots__ = 'foo',
class Bar(object): pass

slotted = Foo()
not_slotted = Bar()

def get_set_delete_fn(obj):
    def get_set_delete():
        obj.foo = 'foo'
        obj.foo
        del obj.foo
    return get_set_delete

and

Copy>>> min(timeit.repeat(get_set_delete_fn(slotted)))
0.2846834529991611
>>> min(timeit.repeat(get_set_delete_fn(not_slotted)))
0.3664822799983085

The slotted access is almost 30% faster in Python 3.5 on Ubuntu.

Copy>>> 0.3664822799983085 / 0.2846834529991611
1.2873325658284342

In Python 2 on Windows I have measured it about 15% faster.

Memory Savings

Another purpose of __slots__ is to reduce the space in memory that each object instance takes up.

My own contribution to the documentation clearly states the reasons behind this:

The space saved over using __dict__ can be significant.

SQLAlchemy attributes a lot of memory savings to __slots__.

To verify this, using the Anaconda distribution of Python 2.7 on Ubuntu Linux, with guppy.hpy (aka heapy) and sys.getsizeof, the size of a class instance without __slots__ declared, and nothing else, is 64 bytes. That does not include the __dict__. Thank you Python for lazy evaluation again, the __dict__ is apparently not called into existence until it is referenced, but classes without data are usually useless. When called into existence, the __dict__ attribute is a minimum of 280 bytes additionally.

In contrast, a class instance with __slots__ declared to be () (no data) is only 16 bytes, and 56 total bytes with one item in slots, 64 with two.

For 64 bit Python, I illustrate the memory consumption in bytes in Python 2.7 and 3.6, for __slots__ and __dict__ (no slots defined) for each point where the dict grows in 3.6 (except for 0, 1, and 2 attributes):

Copy       Python 2.7             Python 3.6
attrs  __slots__  __dict__*   __slots__  __dict__* | *(no slots defined)
none   16         56 + 27216         56 + 112† | †if __dict__ referenced
one    48         56 + 272    48         56 + 112
two    56         56 + 272    56         56 + 112
six    88         56 + 1040   88         56 + 152
11     128        56 + 1040   128        56 + 240
22     216        56 + 3344   216        56 + 408     
43     384        56 + 3344   384        56 + 752

So, in spite of smaller dicts in Python 3, we see how nicely __slots__ scales for instances to save us memory, and that is a major reason you would want to use __slots__.

Just for completeness of my notes, note that there is a one-time cost per slot in the class's namespace of 64 bytes in Python 2, and 72 bytes in Python 3, because slots use data descriptors like properties, called "members".

Copy>>> Foo.foo
<member 'foo' of 'Foo' objects>
>>> type(Foo.foo)
<class 'member_descriptor'>
>>> getsizeof(Foo.foo)
72

Demonstration

To deny the creation of a __dict__, you must subclass object. Everything subclasses object in Python 3, but in Python 2 you had to be explicit:

Copyclass Base(object): 
    __slots__ = ()

now:

Copy>>> b = Base()
>>> b.a = 'a'
Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    b.a = 'a'
AttributeError: 'Base' object has no attribute 'a'

Or subclass another class that defines __slots__

Copyclass Child(Base):
    __slots__ = ('a',)

and now:

Copyc = Child()
c.a = 'a'

but:

Copy>>> c.b = 'b'
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    c.b = 'b'
AttributeError: 'Child' object has no attribute 'b'

To allow __dict__ creation while subclassing slotted objects, just add '__dict__' to the __slots__ (note that slots are ordered, and you shouldn't repeat slots that are already in parent classes):

Copyclass SlottedWithDict(Child): 
    __slots__ = ('__dict__', 'b')

swd = SlottedWithDict()
swd.a = 'a'
swd.b = 'b'
swd.c = 'c'

and

Copy>>> swd.__dict__
{'c': 'c'}

Or you don't even need to declare __slots__ in your subclass, and you will still use slots from the parents, but not restrict the creation of a __dict__:

Copyclass NoSlots(Child): pass
ns = NoSlots()
ns.a = 'a'
ns.b = 'b'

and:

Copy>>> ns.__dict__
{'b': 'b'}

However, __slots__ may cause problems for multiple inheritance:

Copyclass BaseA(object): 
    __slots__ = ('a',)

class BaseB(object): 
    __slots__ = ('b',)
```python

Because creating a child class from parents with both non-empty slots fails:

```python
>>> class Child(BaseA, BaseB): __slots__ = ()
Traceback (most recent call last):
  File "<pyshell#68>", line 1, in <module>
    class Child(BaseA, BaseB): __slots__ = ()
TypeError: Error when calling the metaclass bases
    multiple bases have instance lay-out conflict

If you run into this problem, You could just remove __slots__ from the parents, or if you have control of the parents, give them empty slots, or refactor to abstractions:

Copyfrom abc import ABC

class AbstractA(ABC):
    __slots__ = ()

class BaseA(AbstractA): 
    __slots__ = ('a',)

class AbstractB(ABC):
    __slots__ = ()

class BaseB(AbstractB): 
    __slots__ = ('b',)

class Child(AbstractA, AbstractB): 
    __slots__ = ('a', 'b')

c = Child() # no problem!

Add '__dict__' to __slots__ to get dynamic assignment

Copyclass Foo(object):
    __slots__ = 'bar', 'baz', '__dict__'

and now:

 
2 of 14
285

Quoting Jacob Hallen:

The proper use of __slots__ is to save space in objects. Instead of having a dynamic dict that allows adding attributes to objects at anytime, there is a static structure which does not allow additions after creation. [This use of __slots__ eliminates the overhead of one dict for every object.] While this is sometimes a useful optimization, it would be completely unnecessary if the Python interpreter was dynamic enough so that it would only require the dict when there actually were additions to the object.

Unfortunately there is a side effect to slots. They change the behavior of the objects that have slots in a way that can be abused by control freaks and static typing weenies. This is bad, because the control freaks should be abusing the metaclasses and the static typing weenies should be abusing decorators, since in Python, there should be only one obvious way of doing something.

Making CPython smart enough to handle saving space without __slots__ is a major undertaking, which is probably why it is not on the list of changes for P3k (yet).

Find elsewhere
🌐
Python for the Lab
pythonforthelab.com › blog › using-slots-in-python-limit-dynamic-attribute-creation-and-improve-speed
Using slots in Python: limit dynamic attribute creation and improve speed | Python For The Lab
January 20, 2026 - By defining slots, the programs can have a faster lookup of the data stored. Whether an increase of lookup times of around 15% impacts the overall code will depend on how often we perform the task.
🌐
Codearmo
codearmo.com › python-tutorial › object-orientated-programming-using-slots
Using Slots with Python | Codearmo
March 28, 2025 - When using slots we can get slightly better performance for accessing the attributes from instances. The example below shows somewhere in the region of a 10% improvement when using the slotted version of the point class.
🌐
DEV Community
dev.to › doziestar › speed-upyour-python-classes-with-slot-5ff3
Speed Up Your Python classes with slot - DEV Community
May 8, 2022 - In Python, there is no default ... all its attributes. Usage of __slots__ reduce the wastage of space and speed up the program by allocating space for a fixed amount of attribute...
🌐
DEV Community
dev.to › lead_with_data › understanding-slots-in-python-memory-optimization-and-design-trade-offs-4p87
Understanding `__slots__` in Python: Memory Optimization and Design Trade-offs - DEV Community
February 17, 2026 - Python's dynamic nature makes it flexible, but that flexibility comes with memory overhead. Every object stores its attributes in a dictionary (__dict__), which consumes significant memory especially when creating millions of simple data-holding objects. This article examines __slots__, a Python feature that eliminates this overhead, and explores when it improves code quality versus when it introduces unnecessary complexity.
🌐
Python Tips
book.pythontips.com › en › latest › __slots__magic.html
10. __slots__ Magic — Python Tips 0.1 documentation
Python can’t just allocate a static amount of memory at object creation to store all the attributes. Therefore it sucks a lot of RAM if you create a lot of objects (I am talking in thousands and millions). Still there is a way to circumvent this issue. It involves the usage of __slots__ to tell Python not to use a dict, and only allocate space for a fixed set of attributes.
🌐
YouTube
youtube.com › watch
Slots make Python FASTER and LEANER - YouTube
It might be an old Datsun, but that doesn't mean we can't stick a turbo in it.—If you enjoy my content, consider supporting me on Patreon (or hit the JOIN bu...
Published   June 4, 2022
🌐
CodeConverter
codeconverter.com › articles › python-slots-explained
Python __slots__ Explained: Save Memory, Gain Speed | CodeConverter Blog
February 12, 2026 - However, this flexibility comes at a cost – it uses more memory and can be slower. `__slots__` is a way to tell Python, "Hey, I know exactly what attributes this object is going to have, so don't bother creating a `__dict__` for me." By doing so, you can save memory and improve performance.
🌐
Medium
doziestar.medium.com › speed-upyour-python-classes-with-slot-454e0655a816
Speed Up Your Python classes with slot | by Chidozie C. Okafor | Medium
May 8, 2022 - In Python, there is no default ... all its attributes. Usage of __slots__ reduce the wastage of space and speed up the program by allocating space for a fixed amount of attribute...
🌐
Python.org
discuss.python.org › python help
Slots for class objects? (i.e. avoiding creating __dict__ for classes themselves) - Python Help - Discussions on Python.org
November 21, 2022 - Hi there, I am working on a data-oriented library that uses classes much like any other object instance, and can generate large numbers (tens of thousands, if not low hundreds of thousands) of classes at runtime, by calling the invoking (i.e. effectively by invoking the 3-arg form of type()). I’m looking for ways of cutting down the memory consumption of the library in general.
🌐
FedMSG
fedmsg.com › home › python slots: boosting performance and efficiency
Optimizing Code with Python Slots: An Expert Guide - FedMSG
December 20, 2023 - Slots were introduced in Python primarily to enhance attribute access speed and reduce memory usage. They can significantly improve performance, especially when dealing with a large number of objects, as demonstrated by frameworks like SQLAlchemy.
🌐
LabEx
labex.io › tutorials › python-how-to-optimize-memory-usage-in-a-python-class-using-slots-398043
How to optimize memory usage in a Python class using __slots__ | LabEx
By understanding how to apply __slots__ in your Python classes, you can effectively optimize the memory usage of your applications and improve their overall performance.