This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ariebovenberg
Recipients ariebovenberg, jaraco
Date 2022-01-04.07:57:52
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1641283072.57.0.484148048317.issue46246@roundup.psfhosted.org>
In-reply-to
Content
@jaraco thanks for your quick response.

In short: __slots__ allows class layout to be optimized by replacing the class __dict__ with specific descriptors. This results in a class where only specific attributes can be get/set.

However, you only really get the savings from __slots__ if all base classes also implement it.

An example:

    from pympler.asizeof import asizeof  # checks complete size of objects in memory

    class EmptyNoSlots: pass

    class EmptyWithSlots: __slots__ = ()

    class NoSlots:
        def __init__(self, a, b): self.a, self.b = a, b

    class WithSlots:
        __slots__ = ("a", "b")
        def __init__(self, a, b): self.a, self.b = a, b

    print(asizeof(EmptyNoSlots()))    # 152
    print(asizeof(EmptyWithSlots()))  # 32
    print(asizeof(NoSlots(1, 2)))     # 328
    print(asizeof(WithSlots(1, 2)))   # 112

    # Let's look at inheritance:

    class WithSlotsAndProperBaseClass(EmptyWithSlots):
        __slots__ = ("a", "b")
        def __init__(self, a, b): self.a, self.b = a, b

    class NoSlotsAtAll(EmptyNoSlots):
        def __init__(self, a, b): self.a, self.b = a, b

    class WithSlotsAndBadBaseClass(EmptyNoSlots):
        __slots__ = ("a", "b")
        def __init__(self, a, b): self.a, self.b = a, b

    print(asizeof(WithSlotsAndProperBaseClass(1, 2)))  # 112
    print(asizeof(NoSlotsAtAll(1, 2)))                 # 328
    print(asizeof(WithSlotsAndBadBaseClass(1, 2)))     # 232 -- oh no!

In importlib:

                       list   <- has slots (builtin)
       DeprecatedList(list)   <- no __slots__ defined
EntryPoints(DeprecatedList)   <- defines __slots__

Besides the lost memory savings, because `DeprecatedList` has no slots, you can still do:

    EntryPoints().foo = 6  # setting a random attribute, not the intention.

Further reading: https://stackoverflow.com/a/28059785
History
Date User Action Args
2022-01-04 07:57:52ariebovenbergsetrecipients: + ariebovenberg, jaraco
2022-01-04 07:57:52ariebovenbergsetmessageid: <1641283072.57.0.484148048317.issue46246@roundup.psfhosted.org>
2022-01-04 07:57:52ariebovenberglinkissue46246 messages
2022-01-04 07:57:52ariebovenbergcreate