[Python-ideas] Proposal: Allowing any variable to be used in a 'with... as...' expression

Eric V. Smith eric at trueblade.com
Sun May 19 15:22:27 EDT 2019


On 5/18/2019 8:13 PM, Yonatan Zunger wrote:
...
> For example, this is a good pattern:
> 
> with functionReturningFile(...) as input:
>     doSomething(input)
> 
> 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." However, the following is /not/ valid Python:
> 
> with functionReturningOptionalFile(...) as input:
>     doSomething(input)
> 
> To handle this case, one has a few options. One may only use the 'with' 
> in the known safe cases:
> 
> inputFile = functionReturningOptionalFile(...)
> if inputFile:
>      with inputFile as input:
>          doSomething(input)
> else:
>      doSomething(None)

Either all possible arguments to doSomething() are going to have to 
support the same duck-typed API, or doSomething() is going to have to 
have special logic to handle some types (specifically None in this 
case). Rather than propagate this "might be None" behavior in to 
doSomething(), you'd be much better off with this code (as proposed by 
Steven D'Aprano, but more similar to your example above):

if inputFile := functionReturningOptionalFile(...) is None:
     doSomethingWithNone()
else:
     with inputFile as input:
         doSomething(input)

You're now making the decision about what to do with None as early as 
possible, instead of passing it off to any function you're calling. Now 
doSomething() only need concern itself with file-like objects.

So I think adding "make 'with' work with anything" would just enable bad 
APIs, or duck-typing values just to make them look like other types, 
without actually doing anything (your DevNullFile example further down). 
Neither of these is desirable.

Eric


More information about the Python-ideas mailing list