With a lambda expression in particular, this would be impossible (part of the deal with lambdas is that you can't assign variables inside of them). A workaround for that would be to construct a proper function in advance and then have a lambda call that proper function:
def _f(x):
with x as y:
return do(stuff)
a = [_f(x) for x in someList]
I couldn't get with:
to work inside a lambda, and unfortunately you can't do the open/close routine manually either - I suspect for the same reason (you can't assign variables inside a lambda).
However, using lambdas and the assignment operator introduced in python 3.8, then you can do this:
>>> a = [(lambda x:(f := open(x), f.read(), f.close())[1])(i)
for i in ('hello.txt', 'dunno.txt', 'goodbye.txt')]
>>> print(a)
['Hello', 'I dunno', 'Goodbye']
which uses a tuple as an analogue for putting multiple statements inside a lambda. In a nutshell, it does the following things in order:
- In the first element of the tuple, use an assignment operator to create a named variable
- In the second element of the tuple, perform an operation on the newly-created named variable that returns a value. Leave this value stored in the second element of the tuple.
- In the third element of the tuple, close the resource we opened initially in the first part of the tuple, again by using the named variable. In this case,
file.close()
returns None
, we don't care because it doesn't actually raise an error.
- Tell the lambda to return the second element of the tuple (the one in which we did the important operation on the opened resource).
This takes advantage of both the newly-added Assignment Operator in python 3.8, as well as the fact that tuples are evaluated in order from front to back. Theoretically, you could use this paradigm to implement entire functions inside tuples, though that code would get hellishly complicated. This is unpythonic as-is.
Disclaimers: this method does require opening and closing the file manually (or, in your case, I guess, calling __enter__()
and __exit__()
manually), and as a result it doesn't fully encapsulate the functionality of with
. I have no idea how you would do error handling on this.
I tested this using the python 3.8 beta, and 3.8 isn't going to be properly released until at least October 21 2019. This will not work in any currently-existing version of python before 3.8. I dunno if this qualifies as intended functionality or if it's a bug, so maybe be careful if you choose to try using this for whatever reason.