On Tue, 26 Oct 2021 at 19:25, Chris Angelico <rosuav@gmail.com> wrote:
On Wed, Oct 27, 2021 at 5:05 AM Paul Moore <p.f.moore@gmail.com> wrote:
On Tue, 26 Oct 2021 at 16:48, Eric V. Smith <eric@trueblade.com> wrote:
And also the "No Loss of Abilities If Removed" section sort of applies to late-bound function arguments: there's nothing proposed that can't currently be done in existing Python. I'll grant you that they might (might!) be more newbie-friendly, but I think the bar is high for proposals that make existing things doable in a different way, as opposed to proposals that add new expressiveness to the language.
One issue with not having an introspection capability, which has been bothering me but I've not yet had the time to come up with a complete example, is the fact that with this new feature, you have functions where there's no way to express "just use the default" without knowing what the default actually *is*.
Take for example
def f(a, b=None): if b is None: b = len(a) ...
def g(a, b=>len(a)): ...
Suppose you want to call f as follows:
args = [ ([1,2,3], 2), ([4,5,6], None), ([7,8,9], 4), ]
for a, b in args: f(a, b)
That works fine. But you cannot replace f by g, because None doesn't mean "use the default", and in fact by design there's *nothing* that means "use the default" other than "know what the default is and supply it explicitly". So if you want to do something similar with g (allowing the use of None in the list of tuples to mean "use the default"), you need to be able to introspect g to know what the default is. You may also need to manipulate first-class "deferred expression" objects as well, just to have something you can return as the default value (you could return a string and require the user to eval it, I guess, but that doesn't seem particularly user-friendly...)
I don't have a good solution for this, unfortunately. And maybe it's something where a "good enough" solution would be sufficient. But definitely, it should be discussed in the PEP so what's being proposed is clear.
Wouldn't cases like this be most likely to use *args and/or **kwargs? Simply omitting the argument from those would mean "use the default". Or am I misunderstanding your example here?
Maybe. I don't want to make more out of this issue than it warrants. But I will say that I genuinely would write code like I included there. The reason comes from the fact that I do a lot of ad-hoc scripting, and "copy this text file of data, edit it to look like a Python list, paste it into my code" is a very common approach. I wouldn't bother writing anything generic like f(*args), because it's just a "quick hack". (I'd rewrite it to use f(*args) when I'd done the same copy/paste exercise 20 times, and I was fed up enough to insist that I was allowed the time to "write it properly this time" ;-)) Having the code stop working just because I changed the way the called function handles its defaults would be a nuisance (again, I'm not saying this would happen often, just that I could easily imagine it happening if this feature was available). The function f might well be from a library, or a script, that I wrote for something else, and it might be perfectly reasonable to use the new feature for that other use case. There's no doubt that this is an artificial example - I'm not trying to pretend otherwise. But it's a *plausible* one, in the sort of coding I do regularly in my day job. And it's the sort of awkward edge case where you'd expect there to be support for it, by analogy with similar features elsewhere, so it would feel like a "wart" when you found out you couldn't do it. As I said, I'm not demanding a solution, but I would like to see it acknowledged and discussed in the PEP, just so the trade-offs are clear to people. Paul