On Sat, May 18, 2019 at 07:44:26PM -0700, Yonatan Zunger wrote:
Essentially, a "noop with" improves code health,
I don't think I can accept that as a mere assertion. I'd like to see some concrete evidence that it does.
For example, this is a good pattern:
with functionReturningFile(...) as input: doSomething(input)
Right.
There are many cases where an Optional[file] makes sense as a parameter, as well; for example, an optional debug output stream, or an input source which may either be a file (if provided) or some non-file source (by default). Likewise, there are many cases where a function may naturally return an Optional[file], e.g. "open the file if the user has provided the filename."
If you need to use the word "if" to describe what a piece of code does, then it makes sense for the code to include the "if" keyword.
However, the following is /not/ valid Python:
with functionReturningOptionalFile(...) as input: doSomething(input)
Nor would any of these be safe: functionReturningFileOrNone().write("hello world") (expression_returning_list_or_None).append(1) functionReturningNumberOrNone() + 1 especially since it is so easy to accidentally return None when you didn't intend to: def functionReturningNumber(arg): if arg > 0: return something # oops forgot the case arg <= 0 So I think that it is a mistake to treat None where it would normally not be accepted as a no-op. It is better practice to explicitly test for None and branch, or to use a some sort of None-aware operator or wrapper.
To handle this case, one has a few options. One may only use the 'with' in the known safe cases:
inputFile = functionReturningOptionalFile(...) if inputFile:
Or more expicitly, 'if inputFile is not None:'
with inputFile as input: doSomething(input) else: doSomething(None)
Can you give an example of real-world code where the body of the with and the body of the else are identical? I would expect the more common case will be: if file := MaybeFileOrNone() is None: handle(None) else: with file as f: process(f) or for those using pre-walrus operator Pythons: file = MaybeFileOrNone() if file is None: handle(None) else: with file as f: process(f) -- Steven