[Python-Dev] PEP 567 v3 (original) (raw)
Yury Selivanov yselivanov.ml at gmail.com
Thu Jan 18 00🔞05 EST 2018
- Previous message (by thread): [Python-Dev] PEP 567 v3
- Next message (by thread): [Python-Dev] PEP 567 v3
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Wed, Jan 17, 2018 at 8:53 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
On Wed, Jan 17, 2018 at 2:24 PM, Guido van Rossum <gvanrossum at gmail.com> wrote:
Perhaps you can update the PEP with a summary of the rejected ideas from this thread? The Rejected Ideas section of the PEP is now updated with the below:
I've added two more subsections to Rejected Ideas:
Make Context a MutableMapping
Making the Context
class implement the abc.MutableMapping
interface would mean that it is possible to set and unset variables
using Context[var] = value
and del Context[var]
operations.
This proposal was deferred to Python 3.8+ because of the following:
If in Python 3.8 it is decided that generators should support context variables (see :pep:
550
and :pep:568
), thenContext
would be transformed into a chain-map of context variables mappings (as every generator would have its own mapping). That would make mutation operations likeContext.__delitem__
confusing, as they would operate only on the topmost mapping of the chain.Having a single way of mutating the context (
ContextVar.set()
andContextVar.reset()
methods) makes the API more straightforward.For example, it would be non-obvious why the below code fragment does not work as expected::
var = ContextVar('var')
ctx = copy_context() ctx[var] = 'value' print(ctx[var]) # Prints 'value'
print(var.get()) # Raises a LookupError
While the following code would work::
ctx = copy_context()
def func(): ctx[var] = 'value' # Contrary to the previous example, this would work # because 'func()' is running within 'ctx'. print(ctx[var]) print(var.get()) ctx.run(func)
Have initial values for ContextVars
Nathaniel Smith proposed to have a required initial_value
keyword-only argument for the ContextVar
constructor.
The main argument against this proposal is that for some types
there is simply no sensible "initial value" except None
.
E.g. consider a web framework that stores the current HTTP
request object in a context variable. With the current semantics
it is possible to create a context variable without a default value::
# Framework:
current_request: ContextVar[Request] = \
ContextVar('current_request')
# Later, while handling an HTTP request:
request: Request = current_request.get()
# Work with the 'request' object:
return request.method
Note that in the above example there is no need to check if
request
is None
. It is simply expected that the framework
always sets the current_request
variable, or it is a bug (in
which case current_request.get()
would raise a LookupError
).
If, however, we had a required initial value, we would have
to guard against None
values explicitly::
# Framework:
current_request: ContextVar[Optional[Request]] = \
ContextVar('current_request', initial_value=None)
# Later, while handling an HTTP request:
request: Optional[Request] = current_request.get()
# Check if the current request object was set:
if request is None:
raise RuntimeError
# Work with the 'request' object:
return request.method
Moreover, we can loosely compare context variables to regular
Python variables and to threading.local()
objects. Both
of them raise errors on failed lookups (NameError
and
AttributeError
respectively).
Yury
- Previous message (by thread): [Python-Dev] PEP 567 v3
- Next message (by thread): [Python-Dev] PEP 567 v3
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]