
On Mon, Oct 25, 2021 at 10:39 PM Marc-Andre Lemburg <mal@egenix.com> wrote:
I would prefer to not go down this path.
"Explicit is better than implicit" and this is too much "implicit" for my taste :-)
For simple use cases, this may save a few lines of code, but as soon as you end up having to think whether the expression will evaluate to the right value at function call time, the scope it gets executed in, what to do with exceptions, etc., you're introducing too much confusion with this syntax.
It's always possible to be more "explicit", as long as explicit means "telling the computer precisely what to do". But Python has default arguments for a reason. Instead of simply allowing arguments to be optional, and then ALWAYS having code inside the function to provide values when they are omitted, Python allows us to provide actual default values that are visible to the caller (eg in help()). This is a good thing. Is it "implicit"? Yes, in a sense. But it's very clear what happens if the argument is omitted. The exact same thing is true with these defaults; you can see what happens. The only difference is whether it is a *value* or an *expression* that defines the default. Either way, if the argument is omitted, the given default is used instead.
Exmple:
def process_files(processor, files=>os.listdir(DEFAULT_DIR)):
Some questions: - What happens if dir does not exist ? How would I be able to process the exception in the context of process_files() ?
Well, it wouldn't have a try/except around it, so the exception would simply bubble. Presumably someone creating an API like this would not want to process the exception. And for most functions of this nature, I would not expect to see a try/except. How could it handle a failure of that nature? Letting the exception bubble seems to be the perfect non-action to take.
- Since the same code is valid without the ">", would a user notice that os.listdir() is called in the scope of the function call ?
I don't know. Would they? Would it even matter? The timing of it would make a difference, but the scope is unlikely to. (Unless 'os' is a local name within the function, which seems unlikely. Even then, you'd simply get UnboundLocalError.)
- What if DEFAULT_DIR == '.' ? Would the user notice that the current work dir may have changed compared to when the module with the function was loaded ?
Again, I would assume that that is intentional. If you're specifying that the default is late-evaluated, then you're accepting - possibly intending - that DEFAULT_DIR could be changed, the current directory could change, and the directory context could change. That all seems like good API choice.
Having the explicit code at the start of the function is more flexible and does not introduce such questions.
Then use the explicit code! For this situation, it seems perfectly reasonable to write it either way. But for plenty of other examples, it makes a lot of sense to late-bind in a more visible way. It's for those situations that the feature would exist. ChrisA