<div dir="ltr">You might be interested in <a href="https://github.com/llllllllll/lazy_python">https://github.com/llllllllll/lazy_python</a>, which implements the features you describe but instead of a keyword it uses a decorator.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Feb 17, 2017 at 12:24 AM, Joseph Hackman <span dir="ltr"><<a href="mailto:josephhackman@gmail.com" target="_blank">josephhackman@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Howdy All!<div><br></div><div>This suggestion is inspired by the question on "Efficient debug logging".</div><div><br></div><div>I propose a keyword to mark an expression for delayed/lazy execution, for the purposes of standardizing such behavior across the language.</div><div><br></div><div>The proposed format is:<br>delayed: <expr></div><div>i.e. <a href="http://log.info" target="_blank">log.info</a>("info is %s", delayed: expensiveFunction())</div><div><br></div><div>Unlike 'lambda' which returns a function (so the receiver must be lambda-aware), delayed execution blocks are for all purposes values. The first time the value (rather than location) is read, or any method on the delayed object is called, the expression is executed and the delayed expression is replaced with the result. (Thus, the delayed expression is only every evaluated once).</div><div><br></div><div>Ideally:</div><div>a = delayed: 1+2</div><div>b = a</div><div>print(a) #adds 1 and 2, prints 3</div><div># a and b are now both just 3</div><div>print(b) #just prints 3</div><div><br></div><div>Mechanically, this would be similar to the following:</div><div><pre style="background-color:rgb(43,43,43);color:rgb(169,183,198);font-family:"courier new";font-size:9pt"><span style="color:rgb(204,120,50);font-weight:bold">class </span><span style="font-weight:bold">Delayed</span>():<br>    <span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="color:rgb(178,0,178)">__init__</span>(<span style="color:rgb(148,85,141)">self</span><span style="color:rgb(204,120,50)">, </span>func):<br>        <span style="color:rgb(148,85,141)">self</span>.__func = func<br>        <span style="color:rgb(148,85,141)">self</span>.__executed = <span style="color:rgb(204,120,50);font-weight:bold">False<br></span><span style="color:rgb(204,120,50);font-weight:bold">        </span><span style="color:rgb(148,85,141)">self</span>.__value = <span style="color:rgb(204,120,50);font-weight:bold">None<br></span><span style="color:rgb(204,120,50);font-weight:bold"><br></span><span style="color:rgb(204,120,50);font-weight:bold">    def </span><span style="color:rgb(178,0,178)">__str__</span>(<span style="color:rgb(148,85,141)">self</span>):<br>        <span style="color:rgb(204,120,50);font-weight:bold">if </span><span style="color:rgb(148,85,141)">self</span>.__executed:<br>            <span style="color:rgb(204,120,50);font-weight:bold">return </span><span style="color:rgb(148,85,141)">self</span>.__value.<span style="color:rgb(178,0,178)">__str__</span>()<br>        <span style="color:rgb(148,85,141)">self</span>.__value = <span style="color:rgb(148,85,141)">self</span>.__func()<br>        <span style="color:rgb(148,85,141)">self</span>.__executed = <span style="color:rgb(204,120,50);font-weight:bold">True<br></span><span style="color:rgb(204,120,50);font-weight:bold">        return </span><span style="color:rgb(148,85,141)">self</span>.__value.<span style="color:rgb(178,0,178)">__str__</span>()<br><br><br><span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">function_print</span>(value):<br>    <span style="color:rgb(136,136,198)">print</span>(<span style="color:rgb(0,128,128)">'function_print'</span>)<br>    <span style="color:rgb(136,136,198)">print</span>(value)<br><br><span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">function_return_stuff</span>(value):<br>    <span style="color:rgb(136,136,198)">print</span>(<span style="color:rgb(0,128,128)">'function_return_stuff'</span>)<br>    <span style="color:rgb(204,120,50);font-weight:bold">return </span>value<br><br>function_print(function_<wbr>return_stuff(<span style="color:rgb(0,128,128)">'no_delay'</span>))<br><br>function_print(Delayed(<span style="color:rgb(204,120,50);font-weight:bold">lambda</span>: function_return_stuff(<span style="color:rgb(0,128,128)">'<wbr>delayed'</span>)))<br><br>delayed = Delayed(<span style="color:rgb(204,120,50);font-weight:bold">lambda</span>: function_return_stuff(<span style="color:rgb(0,128,128)">'<wbr>delayed_object'</span>))<br>function_print(delayed)<br>function_print(delayed)</pre></div><div>Unfortunately, due to <a href="https://docs.python.org/3/reference/datamodel.html#special-lookup" target="_blank">https://docs.python.org/3/<wbr>reference/datamodel.html#<wbr>special-lookup</a> , this magic delayed class would need to implement many magic methods, as __getattribute__ is not _always_ called.</div></div>
<br>______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br></blockquote></div><br></div>