[Python-Dev] Idea: Dictionary references

Franklin? Lee leewangzhong+python at gmail.com
Thu Dec 17 10:56:29 EST 2015


(Previous thread was here, by the way:
https://mail.python.org/pipermail/python-dev/2015-December/142437.html)

On Thu, Dec 17, 2015 at 8:48 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Thu, Dec 17, 2015 at 12:53:13PM +0100, Victor Stinner quoted:
>> 2015-12-17 11:54 GMT+01:00 Franklin? Lee <leewangzhong+python at gmail.com>:
>
>> > Each function keeps an indirect, automagically updated
>> > reference to the current value of the names they use,
>
> Isn't that a description of globals()? If you want to look up a name
> "spam", you grab an indirect reference to it:
>
> globals()["spam"]
>
> which returns the current value of the name "spam".

The *current value*. I'm proposing that we instead do this:

    spamref = globals().getref('spam')

Every time we want to find the current, updated value of 'spam', we just do

    spam = spamref.resolve()

which will skip the hash lookup and go directly to the value.

>> > and will never need to look things up again.[*]
>
> How will this work?
>
> Naively, it sounds to me like Franklin is suggesting that on every
> global assignment, the interpreter will have to touch every single
> function in the module to update that name.

A refcell holds a pointer to the location in the dict itself where the
value pointer is. When the value is updated in the dict, the refcell
will not need to be updated.

My original proposal wanted to keep cells in the "real" dict, and
update them. Like so:

    class RefCell:
        __slots__ = ['value']

    class ScopeDict(dict):
        def __getitem__(self, key):
            value = super()[key].value #may raise
            if value is NULL:
                raise KeyError(key)
            return value

        def __setitem__(self, key, value):
            if key in super():
                super()[key].value = value
            else:
                cell = super()[key] = RefCell()
                cell.value = value
        def __delitem__(self, key, value):
            cell = super()[key] #may raise
            if cell.value is NULL:
                raise KeyError(key)
            cell.value = NULL


I realized later that this isn't necessary. Most dict operations don't
need to know about the indirection, so I make the inner dict a normal
dict (with a few more holes than normal). But this would show how you
can avoid manual updates for references.

> And besides, you *still* need to deal with the case that the name isn't
> a global at all, but in the built-ins namespace.

globals() to __builtin__ is a nesting relationship. At the bottom of
the following email, I have a pseudocode implementation which knows
how to deal with nested scopes.
https://mail.python.org/pipermail/python-dev/2015-December/142489.html


More information about the Python-Dev mailing list