Weakrefs to classes that derive from str

Raymond Hettinger vze4rx4y at verizon.net
Wed Mar 30 19:18:41 CEST 2005


[Ron Garret]
> Why doesn't this work?
>
> >>> from weakref import ref
> >>> class C(str): pass
> ...
> >>> ref(C())
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> TypeError: cannot create weak reference to 'C' object
 . . .
>  Everything but strs.

Also subclasses of tuple are not weak referencable.

The issue is in the design of the C structure as a variable-sized immutable
object.  Both strings and tuples allocate as a single unit of memory that holds
both the header information and the content information (the characters in a
string or the array of object pointers for a tuple).  Since the size varies from
one string or tuple to the next, there is no straight-forward way for a subclass
to add an additional header field pointing to a list of weak references.

For lists and dicts, this is not a problem because the object is allocated in
two sections, a fixed size header component and a pointer to another area of
memory to hold the contents of the collection.  This makes it possible for a
subclass to graft-on a weak reference pointer at a known, fixed offset from the
beginning of the header.

There are two ways to fix this.  One is to add a weak reference pointer to every
string object -- that way you wouldn't even have to subclass it.  Another way is
to break the object into two pieces as is done for mutable containers like dicts
and lists.

Both approaches consume time and space.  In general, that is not a big deal, but
fast, memory efficient strings and tuples are at the center of all things
Python.  The need to weak reference this objects is somewhat rare in comparison
to the frequency of their other uses.  It did not make sense to always pay a
time/space penalty just to create the possibility of weak referencing.

While the design decision is unlikely to change, the docs could certainly be
improved.  A doc patch would be welcome.

FWIW, the work-arounds are to weak-reference instances of UserString or to
create a custom class with a has-a relationship instead of an is-a relationship.


Raymond Hettinger





More information about the Python-list mailing list