On Thu, Mar 10, 2016 at 5:20 PM, Michał Żukowski
2016-03-10 17:53 GMT+01:00 Pavol Lisy
: We could discuss if "with expr as var" syntax is more beautiful. (or if it not against There should be one-- and preferably only one --obvious way to do it.)
But why omit context manager semantics in "with expr as var" assignment syntax?
I personally don't like idea that semantics could be context sensitive in this way. (and we could already do pretty complex things in comprehension) I was thinking to reuse "with [expr] as [var]" but I also don't like idea of context sensitive semantics, and I even thought that maybe someone, someday would want to write "content = fp.read() with open('foo.txt') as fp"...
This is my understanding of `with Expr() as Name: Block()`, in pseudocode (ignoring exception handling). _context = Expr() Name = _context.__enter__(...) exec(Block, {"Name": Name}) _context.__exit__(...) Strawman proposal: Extend `with` to allow non-context managers. _context = Expr() if hasattr(_context, '__enter__'): # Context manager. Name = _context.__enter__(...) exec(Block, {"Name": Name}) _context.__exit__(...) else: # Normal object: treat as name bind Name = _context exec(Block, {"Name": Name}) Then you're allowed to write with 5 as x: print(x*2) And if your comprehension `with` receives context managers, they will be treated as such. # Closes each file after reading the second byte. second_bytes = [f.read(1) for fname in fnames with open(fname) as f if f.read(1) != '\0'] # Expanded to a loop. second_bytes = [] for fname in fnames: with open(fname) as f: if f.read(1) != '\0': second_bytes.append(f.read(1)) This breaks TOOWTDI by giving another way to assign. But it might not violate the spirit: I think very few people would trade a simple assignment for a backward assignment and an extra indentation level (!), especially newbies from other languages. TOOWTDI doesn't want competing ways of doing things, and this way isn't competitive. But that means it's a feature not intended for use, and only added for consistency with a new feature. The comprehension `with` will be perfectly aligned and translates naturally to the current `with`. It introduces an inconsistency between context managers and other objects, though. Any code that used to work will still work, but now any code that accidentally uses a non-context manager will not fail fast. It might also make the real use of normal `with` harder to learn. You have a gotcha for people trying to process and store a list of context managers. (Are locks used like this?) I believe that use will be both rare and advanced, so the gotcha is worse than one that is common and beginner-level.