[Python-Dev] PEP 567 v2

Victor Stinner victor.stinner at gmail.com
Wed Jan 3 04:26:28 EST 2018


Le 3 janv. 2018 06:05, "Yury Selivanov" <yselivanov.ml at gmail.com> a écrit :

tuples in Python are immutable, but you can have a tuple with a dict as its
single element. The tuple is immutable, the dict is mutable.

At the C level we have APIs that can mutate a tuple though.

Now, tuple is not a direct analogy to Context, but there are some
parallels.  Context is a container like tuple, with some additional APIs on
top.


Sorry, I don't think that it's a good analogy. Context.run() is a public
method accessible in Python which allows to modify the context. A tuple
doesn't have such method.

While it's technically possible to modify a tuple or a str at C level, it's
a bad practice leading to complex bugs when it's not done carefully: see
https://bugs.python.org/issue30156 property_descr_get() optimization was
fixed twice but still has a bug. I proposed a PR to remove the hack.

Why Context could not inherit from MutableMapping? (Allow ctx.set(var,
> value) and ctx [var] = value.) Is it just to keep the API small: changes
> should only be made using var.set()?
>

Because that would be confusing to end users.

  ctx = copy_context()
  ctx[var] = something

What did we just do?  Did we modify the 'var' in the code that is currently
executing? No, you still need to call Context.run to see the new value for
var.


IMHO it's easy to understand that modifying a *copy* of the current context
doesn't impact the current context. It's one the first thing to learn when
learning Python:

a = [1, 2]
b = a.copy()
b.append(3)
assert a == [1, 2]
assert b == [1, 2, 3]

Another problem is that MutableMapping defines a __delitem__ method, which
i don't want the Context to implement.


I wouldn't be shocked if "del ctx [var]" would raise an exception.

I almost never use del anyway. I prefer to assign a variable to None, since
"del var" looks like C++ destructor whereas it's more complex than a direct
call to the destructor.

But it's annoying to have to call a function with Context.run() whereas
context is just a mutable mapping. It seems overkill to me to have to call
run() to modify a context variable: run() changes temporarely the context
and requires to use the indirect ContextVar API, while I know that
ContextVar.set() modifies the context.

Except of del corner case, I don't see any technical reason to prevent
direct modification of a context.

contextvars isn't new, it extends what we already have: decimal context.
And decimal quick start documentation shows how to modify a context and
then set it as the current context:

>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')

https://docs.python.org/dev/library/decimal.html

Well, technically it doesn't modify a context. An example closer to
contextvars would be:

>>> mycontext = getcontext().copy()
>>> mycontext.prec = 60
>>> setcontext(mycontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')

Note: "getcontext().prec = 6" does modify the decimal context directly, and
it's the *first* example in the doc. But here contextvars is different
since there is no API to get the current API. The lack of API to access
directly the current contextvars context is the main difference with
decimal context, and I'm fine with that.

It's easy to see a parallel since decimal context can be copied using
Context.copy(), it has also multiple (builtin) "variables", it's just that
the API is different (decimal context variables are modified as
attributes), and it's possible to set a context using decimal.setcontext().

Victor
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180103/1d13e58c/attachment.html>


More information about the Python-Dev mailing list