[Python-Dev] Why are contexts also managers? (was r45544 - peps/trunk/pep-0343.txt)
Nick Coghlan
ncoghlan at gmail.com
Sat Apr 22 05:34:29 CEST 2006
Phillip J. Eby wrote:
> At 10:51 AM 4/21/2006 -0400, A.M. Kuchling wrote:
>> On Fri, Apr 21, 2006 at 07:31:35PM +1000, Nick Coghlan wrote:
>>> fit the new definition. So we settled on calling them "context managers"
>>> instead.
>> ...
>>> method. Instead, the new term "manageable context" (or simply "context")
>>> was introduced to mean "anything with a __context__ method". This was OK,
>> Meaning that 'manageable context' objects create and destroy 'context
>> managers'... My view is still that 'context manager' is a terrible
>> name when used alongside objects called 'contexts': the object doesn't
>> manage anything, and it certainly doesn't manage contexts -- in fact
>> it's created by 'context' objects.
>
> And that's more or less why I wrote the documentation the way I did.
>
> Nick, as I understand your argument, it's that we were previously using the
> term "context manager" to mean "thing with __enter__ and __exit__". But
> that was *never* my interpretation.
>
> My understanding of "context manager" was always, "thing that you give to a
> with statement".
Then why didn't you speak up when the discussion was summarised in PEP 343 for
Guido's approval? I said it explicitly:
This PEP proposes that the protocol used by the with statement be
known as the "context management protocol", and that objects that
implement that protocol be known as "context managers". The term
"context" then encompasses all objects with a __context__() method
that returns a context manager object. (This means that all context
managers are contexts, but not all contexts are context managers)
I guess a slight ambiguity came in from the fact I didn't spell out that the
protocol I was referring to was all three methods with __context__ returning
self (i.e. the moral equivalent of the 'iterator protocol'). But the rest of
the paragraph doesn't make any sense otherwise.
Under Resolved Issues, before the recent changes, it said this:
3. After this PEP was originally approved, a subsequent discussion
on python-dev [4] settled on the term "context manager" for
objects which provide __enter__ and __exit__ methods, and
"context management protocol" for the protocol itself. With the
addition of the __context__ method to the protocol, the natural
adjustment is to call all objects which provide a __context__
method "contexts" (or "manageable contexts" in situations where the
general term "context" would be ambiguous).
This is now documented in the "Standard Terminology" section.
*This* is what Guido approved, not what is currently written up in the PEP on
python.org.
> So to me, when we added a __context__ method, we were creating a *new
> object* that hadn't existed before, and we moved some methods on to
> it. Thus, "context manager" still meant "thing you give to the with
> statement" -- and that never changed, from my POV.
That may have been what you personally thought, but it's not what the PEP
said. If you disagreed with the summarisation in the PEP, you should have said
so before Guido approved it, or brought it back to python-dev as a discussion
about changing the standard terminology rather than just "the PEP's confusing,
I want to clear it up" (and completely changing the meaning in the process).
> And that's why I see the argument that we've "reversed" the terminology as
> bogus: to me it's been consistent all along. We just added another object
> *besides* the context manager.
I agree with the second part, but not the first part. Originally we only had
context managers (objects that managed their own state in their
__enter__/__exit__ methods). Jason brought up the point that this excluded
decimal.Context objects because it was extremely difficult to produce a
thread-safe and nesting-safe __enter__/__exit__ pair to manipulate the decimal
context. Without a __context__ method, the decimal module would have had to
provide a separate object for use as a context manager.
So we added contexts to the PEP - objects that could produce a context manager
to work in conjunction with the with statement to manage the state of the
context object. Context managers created in this fashion, instead of operating
on their own state, actually operate on the state of the context that created
them.
This is what got reversed in the contextlib docs - the PEP said that context
managers work on contexts the same way that iterators work on iterables.The
contextlib docs (and the latest version of the PEP) say that contexts
manipulate context managers.
This is just plain bad English. "context" is a passive noun like "iterable" -
it doesn't imply any sort of active operation. "context manager" on the other
hand describes an actor doing something, just like "iterator" does.
>
> Note too that the user of the "with" statement doesn't know that this other
> object exists, and in fact sometimes it doesn't actually exist, it's the
> same object. None of this is relevant for the with-statement user, only
> the context manager. So there's no reason (IMO) to monkey with the
> definition of "context manager" as "thing you use in a with statement".
Paraphrasing:
Note too that the user of the "for" statement doesn't know that this other
object exists, and in fact sometimes it doesn't actually exist, it's the
same object. None of this is relevant for the for-statement user, only
the iterator writer. So there's no reason (IMO) to monkey with the
definition of "iterator" as "thing you use in a for statement".
"context" is to "context manager" as "iterable" is to "iterator". Why is this
a difficult concept? The only difference is that we have a builtin to do the
obj.__iter__() call, but have to do obj.__context__() explicitly.
And while "thing you use in a with statement" may have been the definition of
context manager in your mind, it was never the definition in the PEP.
> Now, I get your point about @contextmanager on a __context__ method, and I
> agree that that seems backwards at first. What I don't see is how to
> change the terminology to handle that subtlety in a way that doesn't muck
> up the basically simple definitions that are in place now.
Easy: we go back to the definitions we used in the originally approved PEP,
where "context" precisely paralleled "iterable" and "context manager"
precisely paralleled "iterator".
Leverage off people's long experience with iterators and iterables instead of
doing something deliberately different.
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-Dev
mailing list