2

Here is the example of my implementation:

class FileHandler:
    __slots__ = ("_target_path",)

    def __init__(self, target_path: Path) -> None:
        self._target_path = target_path

class Downloader(FileHandler):
    __slots__ = ("_url", "_downloaded_bytes")

    def __init__(self, target_path: Path, url: str) -> None:
        super().__init__(target_path)
        self._url = url
        self._downloaded_bytes = 0

... There is more stuff but that is not necessary here. In short, all the methods work in the downlaoder including download() and they all use the target_path as well as the _url and the _downlaoded_bytes, now here is something funny when I print the following:

Test and results in the next field...

foo.py

from pathlib import Path

from solutions.file.downloader import Downloader


url = "https://www.unicode.org/Public/UCD/latest/ReadMe.txt"
path = Path(__file__).parent / "unicode.txt"


def foo():
    downloader = Downloader(path, url)

    return downloader.__slots__


if __name__ == "__main__":
    foo_val = foo()
    print(foo_val) if not foo_val is None else None

--- CONSOLE OUTPUT BELOW LINE ---

('_url', '_downloaded_bytes')

--- END OF OUTPUT ---

So, it somehow appears to work. However, is my implementation correct? Also, does it still work like legitimate slots or does it decide not to use slots and uses more memory instead?

I am still a beginner so excuse my ignorance. All answers are appreciated. Thank you!

2
  • 2
    It's like any other class attribute. The assignment in the subclass overrides the assignment in the parent class.
    – Barmar
    Commented Jun 26 at 20:33
  • Actually this one seems weird. I tested it out by printing the memory a subclass uses compared to the base class if the base class slots is an empty tuple and it seems that the subclass doesn't inherit the slots at all. When neither class uses slots they all use the same memory. When the base class has empty slots it uses much less but the subclass doesn't change. Commented Jun 28 at 9:49

1 Answer 1

1

Indeed, __slots__ does not work quite like other attributes, especially it is NOT overridden by the subclass.

Explanation and answer according to the official Python docs at data model refs

The action of a __slots__ declaration is not limited to the class where it is defined. __slots__ declared in parents are available in child classes. However, child subclasses will get a __dict__ and __weakref__ unless they also define __slots__ (which should only contain names of any additional slots).

Solution You NEED to declare __slots__ in each subclass that you want to avoid using __dict__ for the purpose of efficiency and space. If you are not adding any new attributes then you have to use the following:

__slots__ = tuple()

This will ensure that you inherit the desired effect.

1
  • Thank you for the formatting! I now learned what the escape char is (`), haha. Commented Jul 6 at 15:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.