<div dir="rtl"><div style dir="ltr">What I'd personally like to see is a combined for-with, something like</div><div style dir="ltr"><br></div><div style dir="ltr">    x = [x.split() for x with in open(thisfile)]</div>
<div style dir="ltr"><br></div><div style dir="ltr">and</div><div style dir="ltr"><br></div><div style dir="ltr">    for x with in open(somefile):</div><div style dir="ltr">        print(x)</div><div style dir="ltr"><br></div>
<div style dir="ltr">A with expression might help too,</div><div style dir="ltr"><br></div><div style dir="ltr">---</div><div style dir="ltr">Elazar</div></div><div class="gmail_extra"><br><br><div class="gmail_quote"><div dir="ltr">
2014-02-20 20:50 GMT+02:00 Yann Kaiser <span dir="ltr"><<a href="mailto:kaiser.yann@gmail.com" target="_blank">kaiser.yann@gmail.com</a>></span>:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
As an alternative to the recently-proposed "except expression", I<br>
suggested this in its thread. I was recommended to post this<br>
separately, as, while it is related, it is different enough from the<br>
original idea.<br>
<br>
The general idea is to extend the context manager protocol so that it<br>
can produce a return value in alternative to simply letting or denying<br>
an exception from propagating, and introduce an inline form of "with".<br>
<br>
The motivation behind is, in all honesty, that I find the suggested<br>
except-expressions from PEP 463 to be too verbose to inline, and that<br>
context managers have a much broader reach. The motivation from the<br>
aforementioned PEP(inline evaluation to a "default" expression upon<br>
catching an exception) also applies here.<br>
<br>
It could look a bit like this:<br>
<br>
    contexted_expr with context_manager as c<br>
<br>
Once more, the rationale from PEP 463 also applies here, in that we<br>
can shift "easy defaulting" from being a potential concern for the<br>
callee to being always available to the caller through new syntax.<br>
Likewise, currently in-lining the use of a context manager can be<br>
done, but only through manually encapsulating what would be the<br>
context-ed code through lambdas or eval.<br>
<br>
A full example could be as such:<br>
<br>
    class Default(object):<br>
        """Context manager that returns a given default value when an exception<br>
        is caught."""<br>
<br>
        def __init__(self, value, *exception_types):<br>
            self.value = value<br>
            self.exception_types = exception_types or BaseException<br>
<br>
        def __enter__(self):<br>
            pass<br>
<br>
        def __exit__(self, typ, val, tb):<br>
            if typ and issubclass(typ, self.exception_types):<br>
                return True, self.value<br>
<br>
<br>
    lst = [1, 2]<br>
    # found is assigned 2<br>
    found = lst[1] with Default(0, IndexError)<br>
    # not found is assigned 0<br>
    not_found = lst[2] with Default(0, IndexError)<br>
<br>
The different interpretation of __exit__'s return value is probably<br>
something that needs to be discussed. In this form, it is potentially<br>
backwards-incompatible, so a preferable alternative would be a<br>
different special method, perhaps:<br>
<br>
    def __return__(self, typ, val, tb, ret):<br>
        if typ is None:<br>
            return False, ret * 3<br>
        elif isinstance(typ, IndexError):<br>
            return True, 10<br>
<br>
The alternatively-named special method would take priority over<br>
__exit__ and take over its augmented function:<br>
If no exception has occurred, typ, val, and tb are given None, as with<br>
the regular __exit__ incarnation, but ret, or whatever is the fourth<br>
positional parameter, is supplied with what "expr" evaluated to in<br>
"expr with cmgr". When an exception has occurred or propagated, typ,<br>
val and tb are set to the appropriate values(Since exceptions now keep<br>
their traceback as an attribute, maybe only supply the exception<br>
object?), and ret is given None.<br>
If the return value of this special method is None, the exception or<br>
return value is propagated as is. If it is a sequence, the first<br>
element is used like the return value of __exit__ would be, and the<br>
second element is used to (re-)place the return value of the whole<br>
with expression. When multiple context managers are being chained, the<br>
return value/exception is forwarded much like it is with twisted's<br>
Deferreds.<br>
<br>
In the use case of providing a default value, if the default value is<br>
the product of an expensive operation, an alternative context manager<br>
can be designed to compute the value only when needed, for instance:<br>
<br>
    fa = factorials[n] with SetDefault(factorials, n, lambda: math.factorial(n))<br>
<br>
Other examples using existing context managers:<br>
<br>
    contents = f.read() with open('file') as f<br>
<br>
    with open('file') as f:<br>
        contents = f.read()<br>
<br>
<br>
<br>
    d = Decimal(1) / Decimal(7) with Context(prec=5)<br>
<br>
    with Context(prec=5):<br>
        d = Decimal(1) / Decimal(7)<br>
<br>
I think that's all I can think of so far. Sorry as this might be a<br>
little too detailed to start with, so I will remind you there is no<br>
offense in rethinking any of what I posted here.<br>
<br>
-yk<br>
_______________________________________________<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" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div><br></div>