[Python-Dev] PEP 567 pre v3

Chris Jerdonek chris.jerdonek at gmail.com
Thu Jan 11 02:39:36 EST 2018


On Wed, Jan 10, 2018 at 10:58 PM, Yury Selivanov
<yselivanov.ml at gmail.com> wrote:
> On Thu, Jan 11, 2018 at 10:35 AM, Chris Jerdonek
> <chris.jerdonek at gmail.com> wrote:
>> On Mon, Jan 8, 2018 at 11:02 PM, Nathaniel Smith <njs at pobox.com> wrote:
>>> Right now, the set of valid states for a ContextVar are: it can hold
>>> any Python object, or it can be undefined. However, the only way it
>>> can be in the "undefined" state is in a new Context where it has never
>>> had a value; once it leaves the undefined state, it can never return
>>> to it.
>>
>> I know Yury responded to one aspect of this point later on in the
>> thread. However, in terms of describing the possible states without
>> reference to the internal Context mappings, IIUC, wouldn't it be more
>> accurate to view a ContextVar as a stack of values rather than just
>> the binary "holding an object or not"? This is to reflect the number
>> of times set() has been called (and so the number of times reset()
>> would need to be called to "empty" the ContextVar).
>
>
> But why do you want to think of ContextVar as a stack of values?  Or
> as something that is holding even one value?

I was primarily responding to Nathaniel's comment about how to
describe or talk about the state and not necessarily advocating that
view.

But to your question, like it or not, I think the API encourages this
way of thinking because the get() method is on the ContextVar itself,
and so it's the ContextVar which is doing the looking up rather than
just fulfilling the role of a key name. The API brings to mind other
containers and things holding values like dict.get(), queue.get(),
BytesIO.getvalue(), and container type's object.__getitem__(), etc. So
I think one will need to be prepared for many or most users having
this conception with the current API. (I think renaming to something
like ContextVar.lookup() or even ContextVar.value() would go a long
way towards dispelling that, but Guido said earlier in the thread that
he likes the shorter name.)

> Do Python variables hold/envelope objects they reference?  No, they
> don't.  They are simple names and are used to lookup objects in
> globals/locals dicts.  ContextVars are very similar!  They are *keys*
> in Context objects—that is it.

Python variables don't hold the objects. But the analogy also doesn't
quite match because variables also don't have get() methods. It's
Python which is doing the looking up in that case rather than the
variable itself. With ContextVars, it's serving both roles of name and
thing doing the looking up.

This is one reason why I suggested several days ago that I thought
something like contextvars.get(key) (where key is a ContextVar) would
be a less confusing API. That way the ContextVar / ContextKey(?) would
only be acting as a key and not also be responsible for doing the
lookup and knowing about what is containing it.

--Chris


>
> ContextVar.default is returned by ContextVar.get() when it cannot find
> the value for the context variable in the current Context object.  If
> ContextVar.default was not provided, a LookupError is raised.
>
> The reason why this is simpler for regular variables is because they
> have a dedicated syntax.  Instead of writing
>
>     print(globals()['some_variable'])
>
> we simply write
>
>     print(some_variable)
>
> Similarly for context variables, we could have written:
>
>    print(copy_context()[var])
>
> But instead we use a ContextVar.get():
>
>    print(var.get())
>
> If we had a syntax support for context variables, it would be like this:
>
>    context var
>    print(var)   # Lookups 'var' in the current context
>
> Although I very much doubt that we would *ever* want to have a
> dedicated syntax for context variables (they are very niche and are
> only needed in some very special cases), I hope that this line of
> thinking would help to clear the waters.
>
> Yury


More information about the Python-Dev mailing list