25.10.21 21:26, firstname.lastname@example.org пише:
I've been thinking for a while that it would be good to be able to use context managers in an expression context, and I haven't been able to come up with any arguments against it (although it may not be to everyone's taste) and I can't see any sign that it's come up before (although the words of it don't make very specific search terms). My suggestion is that a "with" clause could be written after an expression (consistent with the conditional operator being written with "if" after the first expression).
In general, this would be: a(b) with c(d) as b or it could allow multiple context managers: a(b, c) with d(e) as b, f(g) as c
My original motivating example was this:
if name.startswith("https://"): data = requests.get(name).json() else: with open(name) as stream: data = json.load(stream)
which I'd much rather be able to write with a single expression:
data = (requests.get(name).json() if name.startswith("https://") else (json.load(stream) with open(name) as stream))
It would behave just like a "with" statement, but pass a value / values back.
I was going to propose this idea for discussion but did not have enough time to formulate it.
It is not just a "what if we combine two random features idea", it would cover most cases of recurrent requests for adding functions which merge open() and json.load(), etc or adding new very specialized methods to the Path object. Currently you can write
with open(filename, 'rb') as f: data = json.load(f)
The only minor drawback of this idiom is that it is not expression (but you always can write a new function). If you could write
data = json.load(f) with open(filename, 'rb') as f
this counter-argument will disappear.
Now, Mark Gordon asked a good question -- what to do if the context manager suppresses an exception. We do not have value and we do not have exception. The only answer I have -- raise a RuntimeError (or other specialized exception). It should be an error to use context managers which suppress exceptions in the "with" expression. Maybe there are better ideas.
Before adding the "with" expressions we should consider other feature: the "with" clause in comprehensions.
Currently comprehensions can contain "for" and "if" clauses. There should be at least one "for" clause and it should be the first clause. I propose to add the with clause. It will be interpreted the same way as "if" and nested "for" clauses. [expr for x in iterable if cond() with cm() as y] should be equivalent to:
result =  for x in iterable: if cond(): with cm() as y: result.append(expr)
It should be discussed because there is a conflict between its syntax and the "with" expression. The "with" clause should have priority over the "with" expression (as the "if" clause has priority over the "if" expression), but it is a breaking change if the latter will be implemented first.