Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>No, unfortunately there is no way to do anything with the <code>__slots__</code> after the class is created (and that's when the decorators on them are called). The only way is to use a metaclass, and modify/add <code>__slots__</code> before calling the <code>type.__new__</code>.</p> <p>An example of such a metaclass:</p> <pre><code>class MetaA(type): def __new__(mcls, name, bases, dct): slots = set(dct.get('__slots__', ())) slots.add('y') dct['__slots__'] = tuple(slots) return super().__new__(mcls, name, bases, dct) class BaseA(metaclass=MetaA): pass class A(BaseA): __slots__ = ('x',) def __init__(self): self.x = 1 self.y = 2 print(A().x, A().y) </code></pre> <p>Without metaclasses, you can do some magic and copy everything from the defined class and create a new one on the fly, but that code smells ;)</p> <pre><code>def decorator(cls): slots = set(cls.__slots__) slots.add('y') dct = cls.__dict__.copy() for name in cls.__slots__: dct.pop(name) dct['__slots__'] = tuple(slots) return type(cls)(cls.__name__, cls.__bases__, dct) @decorator class A: __slots__ = ('x',) def __init__(self): self.x = self.y = 42 print(A().x, A().y) </code></pre> <p>The main disadvantage of such code, is that if someone applies another decorator, before yours one, and, let's say, creates a reference to the decorated class somewhere, then they will end up storing reference to a different class. Same for metaclasses - they will execute twice. So, the metaclass approach is better, since there are no side-effects.</p> <hr> <p>The definitive answer of why you can't really change <code>__slots__</code> after the class is created depends on implementation details of the python interpreter you're working with. For instance, in CPython, for each slot you defined, class has a descriptor (see <code>PyMemberDescr_Type</code> &amp; <code>PyMemberDef</code> struct in CPython source code), that has an offset parameter of where the slot value is aligned in internal object storage. And you simply have no instruments of manipulating such things in public Python API. You trade flexibility for less memory usage (again, in CPython, as in PyPy you get the same memory effect automatically for all your classes).</p> <p>If modification of <code>__slots__</code> is absolutely required, you can, probably, write a C extension (or work with <code>ctypes</code>) and do it, but that's hardly a reliable solution.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload