New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
importlib.metadata.DeprecatedList appears to be missing __slots__ #90404
Comments
(as instructed in bpo-46244, I've created this ticket) The subclass This appears to be a mistake. If so, I'd like to create a PR to fix it. |
Perhaps it is a mistake. The It's not obvious to me what the danger is in defining __slots__ in a child class but not in a parent. Can you point me to resources or examples that help me understand the concern or missed expectation? The primary motivation behind defining slots is to help ensure immutability. Does the lack of slots violate that expectation? Convince me of the value of fixing this concern and please feel free to proceed with a PR. |
@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
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:
EntryPoints(DeprecatedList) <- defines __slots__ Besides the lost memory savings, because
Further reading: https://stackoverflow.com/a/28059785 |
Today I learned something. Thanks Arie. Yes, I agree that's a mistake. Perhaps the test suite should also have a test to capture the missed expectation (that __dict__ should not be present or setting attributes on EntryPoints instances should fail). |
I'm pretty sure both EntryPoints and DeprecatedList were introduced in Python 3.10, so 3.9 and 3.8 aren't relevant. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: