On 30/07/18 21:15, Rudy Matela wrote:
> Hello,
> 
> Do you think it would be nice to allow with statements inside genexps or
> list comprehensions?  The functions __enter__ and __exit__ would be
> automatically called as iterables are traversed.  I am thinking of
> drafting a PEP about this.  Examples:
> 
> 
> This 
> 
>       g = (f.read() for fn in filenames with open(fn) as f)
> 
> would be equivalent to the following use of a generator function:
> 
>       def __gen():
>               for fn in filenames:
>                       with open(fn) as f:
>                               yield f.read()
>       g = __gen()


To sail around Oscar's concern, this should rather be

def __gen():
    for fn in filenames:
        with open(fn) as f:
            _v = f.read()
        yield _v

But in this case I think it'd be clearer to make it an expression rather
than a generator expression term:

    g = (f.read() with open(fn) as f for fn in filenames)

where

    _ = f.read() with open(fn) as f

is equivalent to

    with open(fn) as f:
        _ = f.read()

Currently possibly (if silly) alternative:

from functools import wraps

class with_one_use:
    def __init__(self, context):
        self.__context = context

    def __getattr__(self, name):
        exc1 = False
        obj = self.__context.__enter__()
        try:
            temp = getattr(obj, name)
        except:
            exc1 = True
            if not self.__context.__exit__(*sys.exc_info()):
                raise
        else:
            if callable(temp):
                @wraps(temp)
                def f(*args, **kwargs):
                    exc2 = False
                    try:
                        return temp(*args, **kwargs)
                    except:
                        exc2 = True
                        if not self.__context.__exit__(*sys.exc_info()):
                            raise
                    finally:
                        if not exc2:
                            self.__context.__exit__(None, None, None)
                exc1 = True
                return f
            else:
                return temp
        finally:
            if not exc1:
                self.__context.__exit__(None, None, None)


g = (with_one_use(open(fn)).read() for fn in filenames)


-- Thomas

> 
> 
> This
> 
>       list = [f.read() for fn in filenames with open(fn) as f]
> 
> would be equivalent to the following:
> 
>       list = []
>       for fn in filenames:
>               with open(fn) as f:
>                       list.append(f.read())
> 
> --
> Rudy
> _______________________________________________
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> 

_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to