20

Consider the following code:

from weakref import ref

class Klass(object):
    # __slots__ = ['foo']
    def __init__(self):
        self.foo = 'bar'

k = Klass()
r = ref(k)

it works but when I uncomment the __slots__ it breaks with TypeError: "cannot create weak reference to 'Klass' object" under Python 2.6.

Please, does anyone know if this is an inherent limitation of Python and __slots__ or if it is a bug? How to work-around it?

Ecir Hana
  • 10,864
  • 13
  • 67
  • 117

2 Answers2

27

Without a __weakref__ variable for each instance, classes defining __slots__ do not support weak references to its instances. If weak reference support is needed, then add __weakref__ to the sequence of strings in the __slots__ declaration.

From the Python documentation.

If you add __weakref__ to __slots__, your code will work:

>>> from weakref import ref
>>>
>>> class Klass(object):
>>>     __slots__ = ['foo', '__weakref__']
>>>     def __init__(self):
>>>         self.foo = 'bar'
>>> k = Klass()
>>> k
 => <__main__.Klass object at ...>
>>> r = ref(k)
>>> r
 => <weakref at ...; to 'Klass' at ...>
Sam van Kampen
  • 973
  • 9
  • 17
  • 2
    That's a great answer, but I couldn't google it. To improve it's indexing I quote the error message that occurs when facing this exact issue creating reference to object with __slots__: The message is `TypeError: cannot create weak reference to given object`. It occurs in python 2.7, 3.5, 3.6, 3.7, but what interesting - does not in pypy and pypy3. – Mikaelblomkvistsson Dec 12 '18 at 14:54
8

You have to add __weakref__ to the list of slots. It's one of the __slots__ quirks. Prior to 2.3, even this didn't work, but luckily your version isn't that old.