[Python-ideas] Map-then-filter in comprehensions
Franklin? Lee
leewangzhong+python at gmail.com
Thu Mar 10 21:58:27 EST 2016
On Thu, Mar 10, 2016 at 5:20 PM, Michał Żukowski <thektulu.pp at gmail.com> wrote:
> 2016-03-10 17:53 GMT+01:00 Pavol Lisy <pavol.lisy at gmail.com>:
>> 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.
More information about the Python-ideas
mailing list