[Python-ideas] with expression

Andrew Barnert abarnert at yahoo.com
Thu Feb 20 21:02:56 CET 2014


On Feb 20, 2014, at 10:54, אלעזר <elazarg at gmail.com> wrote:

> What I'd personally like to see is a combined for-with, something like
> 
>     x = [x.split() for x with in open(thisfile)]
> 
> and
> 
>     for x with in open(somefile):
>         print(x)

This has two prepositions in a row, attempting to share the same object. That isn't readable in English, or any other human language. Trying to parse it makes my brain hurt.

Also, it obviously only works for objects which are iterable, and are also context managers whose context is self--which basically means file-like objects only. This is why we have the "as" clause in with statements (and in the proposed with expression).

If you reorganize it to make more sense:

    x = [x.split() for x in f with open(thisfile) as f]

... then it's exactly the same thing I proposed last year, which was shot down for good reasons.

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


More information about the Python-ideas mailing list