<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Tue, Aug 7, 2018 at 11:16 PM Ken Hilton <<a href="mailto:kenlhilton@gmail.com">kenlhilton@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">...</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">Now, let's take a look at the following scenario:</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">    def read_multiple(*filenames):</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">        for filename in filenames:</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">            with open(filename) as f:</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">                yield f.read()</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">Can you spot the problem? The "with open(filename)" statement is supposed to ensure that the file object is disposed of properly. However, the "yield f.read()" statement suspends execution within the with block, so if this happened:</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">    for contents in read_multiple('chunk1', 'chunk2', 'chunk3'):</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">        if contents == 'hello':</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">            break</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small;color:#0000ff">and the contents of "chunk2" were "hello" then the loop would exit, and "chunk2" would never be closed! Yielding inside a with block, therefore, doesn't make sense and can only lead to obscure bugs.</div></div></blockquote><div><br></div><div>Instead of disallowing code, this is a case for allowing with expressions:<div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace;color:rgb(0,0,255)">    def read_multiple(*filenames):</div><div class="gmail_default" style="font-family:monospace,monospace;color:rgb(0,0,255)">        for filename in filenames:</div><div class="gmail_default" style="font-family:monospace,monospace;color:rgb(0,0,255)">            yield (f.read() with open(filename) as f)</div></div><div class="gmail_default" style="font-family:monospace,monospace;color:rgb(0,0,255)"><br></div><div class="gmail_default" style="font-family:monospace,monospace;color:rgb(0,0,255)"><span style="color:rgb(0,0,0);font-family:sans-serif;font-size:13px">Elazar</span></div></div></div></div>