[Python-Dev] Multiline with statement line continuation

yoav glazner yoavglazner at gmail.com
Wed Aug 13 19:08:51 CEST 2014


On Aug 13, 2014 7:04 PM, "Akira Li" <4kir4.1i at gmail.com> wrote:
>
> Nick Coghlan <ncoghlan at gmail.com> writes:
>
> > On 12 August 2014 22:15, Steven D'Aprano <steve at pearwood.info> wrote:
> >> Compare the natural way of writing this:
> >>
> >> with open("spam") as spam, open("eggs", "w") as eggs,
frobulate("cheese") as cheese:
> >>     # do stuff with spam, eggs, cheese
> >>
> >> versus the dynamic way:
> >>
> >> with ExitStack() as stack:
> >>     spam, eggs = [stack.enter_context(open(fname), mode) for fname,
mode in
> >>                   zip(("spam", "eggs"), ("r", "w")]
> >>     cheese = stack.enter_context(frobulate("cheese"))
> >>     # do stuff with spam, eggs, cheese
> >
> > You wouldn't necessarily switch at three. At only three, you have lots
> > of options, including multiple nested with statements:
> >
> >     with open("spam") as spam:
> >         with open("eggs", "w") as eggs:
> >             with frobulate("cheese") as cheese:
> >                 # do stuff with spam, eggs, cheese
> >
> > The "multiple context managers in one with statement" form is there
> > *solely* to save indentation levels, and overuse can often be a sign
> > that you may have a custom context manager trying to get out:
> >
> >     @contextlib.contextmanager
> >     def dish(spam_file, egg_file, topping):
> >         with open(spam_file), open(egg_file, 'w'), frobulate(topping):
> >             yield
> >
> >     with dish("spam", "eggs", "cheese") as spam, eggs, cheese:
> >         # do stuff with spam, eggs & cheese
> >
> > ExitStack is mostly useful as a tool for writing flexible custom
> > context managers, and for dealing with context managers in cases where
> > lexical scoping doesn't necessarily work, rather than being something
> > you'd regularly use for inline code.
> >
> > "Why do I have so many contexts open at once in this function?" is a
> > question developers should ask themselves in the same way its worth
> > asking "why do I have so many local variables in this function?"
>
> Multiline with-statement can be useful even with *two* context
> managers. Two is not many.
>
> Saving indentations levels along is a worthy goal. It can affect
> readability and the perceived complexity of the code.
>
> Here's how I'd like the code to look like:
>
>   with (open('input filename') as input_file,
>         open('output filename', 'w') as output_file):
>       # code with list comprehensions to transform input file into output
file
>
> Even one additional unnecessary indentation level may force to split
> list comprehensions into several lines (less readable) and/or use
> shorter names (less readable). Or it may force to move the inline code
> into a separate named function prematurely, solely to preserve the
> indentation level (also may be less readable) i.e.,
>
>   with ... as input_file:
>       with ... as output_file:
>           ... #XXX indentation level is lost for no reason
>
>   with ... as infile, ... as outfile: #XXX shorter names
>       ...
>
>   with ... as input_file:
>       with ... as output_file:
>           transform(input_file, output_file) #XXX unnecessary function
>
> And (nested() can be implemented using ExitStack):
>
>   with nested(open(..),
>               open(..)) as (input_file, output_file):
>       ... #XXX less readable
>
> Here's an example where nested() won't help:
>
>   def get_integers(filename):
>       with (open(filename, 'rb', 0) as file,
>             mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as
mmapped_file):
>           for match in re.finditer(br'\d+', mmapped_file):
>               yield int(match.group())
>
> Here's another:
>
>   with (open('log'+'some expression that generates filename', 'a') as
logfile,
>         redirect_stdout(logfile)):
>       ...
>
Just a thought, would it bit wierd that:
with (a as b, c as d): "works"
with (a, c): "boom"
with(a as b, c): ?

>
> --
> Akira
>
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
https://mail.python.org/mailman/options/python-dev/yoavglazner%40gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20140813/0f7908cc/attachment-0001.html>


More information about the Python-Dev mailing list