Default Value

Rotwang sg552 at hotmail.co.uk
Fri Jun 21 19:40:51 EDT 2013


On 21/06/2013 19:26, Rick Johnson wrote:
> On Friday, June 21, 2013 12:47:56 PM UTC-5, Rotwang wrote:
>> It isn't clear to me from your posts what exactly you're
>> proposing as an alternative to the way Python's default
>> argument binding works. In your version of Python, what
>> exactly would happen when I passed a mutable argument as a
>> default value in a def statement? E.g. this:
>>
>>   >>> a = [1, 2, 3]
>>   >>> a.append(a)
>>   >>> b = object()
>>   >>> def f(x = [None, b, [a, [4]]]):
>> ...     pass # do something
>>
>> What would you like to see the interpreter do in this case?
>
> Ignoring that this is a completely contrived example that has
> no use in the real world, here are one of three methods by
> which i can handle this:

I didn't ask what alternative methods of handling default argument 
binding exist (I can think of several, but none of them strikes me as 
preferable to how Python currently does it). I asked what would happen 
in /your/ version of Python. Which of the alternatives that you present 
would have been implemented, if you had designed the language?


> ============================================================
>   The Benevolent Approach:
> ============================================================
> I could cast a "virtual net" over my poor lemmings before
> they jump off the cliff by throwing an exception:
>
>    Traceback (most recent screw-up last):
>     Line BLAH in SCRIPT
>      def f(x = [None, b, [a, [4]]]):
>    ArgumentError: No mutable default arguments allowed!

So how does the interpreter know whether an arbitrary object passed as a 
default value is mutable or not?

Not that it really matters. Elsewhere in this thread you wrote:

> Let's imagine for a second if Python allowed mutable keys in
> a dictionary,

which it does

> would you be surprised if you used a mutable
> for a key, then you mutated the mutable key, then you could
> not access the value from the original key?
>
>  ## Imaginary code ##
>  py> lst = [3]
>  py> d = {1:2, lst:4}
>  py> lst.append(10)
>  py> d[lst]
>  opps, KeyError!
>
> Would you REALLY be so surprised? I would not. But more
> importantly, does Python need to protect you from being such
> an idiot? I don't think so!

Now, I don't really believe that you think that the user shouldn't be 
protected from doing one idiotic thing with mutable dict keys but should 
be protected from doing another idiotic thing with mutable default 
arguments, especially as you've already been given a use case for the 
latter. So I assume that The Benevolent Approach is not the approach you 
would have gone for if you had designed the language, right? If so then 
let's ignore it.


> ============================================================
>   The Apathetic Approach:
> ============================================================
> I could just assume that a programmer is responsible for the
> code he writes. If he passes mutables into a function as
> default arguments, and then mutates the mutable later, too
> bad, he'll understand the value of writing solid code after
> a few trips to exception Hell.

It seems to me that this is exactly what currently happens.


> ============================================================
>   The Malevolent Approach (disguised as beneva-loon-icy):
> ============================================================
> I could use early binding to confuse the hell out of him and
> enjoy the laughs with all my ivory tower buddies as he falls
> into fits of confusion and rage. Then enjoy again when he
> reads the docs. Ahh, the gift that just keeps on giving!

My question was about how you think the language should work, not about 
what your buddies should or shouldn't enjoy. In terms of how a language 
actually works, is there any difference between The Malevolent Approach 
and The Apathetic Approach? And is there any difference between either 
of them and what Python currently does?


> ============================================================
>   Conclusion:
> ============================================================
> As you can probably guess the malevolent approach has some
> nice fringe benefits.
>
> You know, out of all these post, not one of you guys has
> presented a valid use-case that will give validity to the
> existence of this PyWart -- at least not one that CANNOT be
> reproduced by using my fine examples.

Of course using a mutable default as a cache can be reproduced by other 
means, as can another common use case that I don't think anyone's 
mentioned yet (defining functions parametrised by variables whose values 
aren't known until runtime). That's hardly an argument against it - you 
might as well argue that Python shouldn't have decorators, or that it 
shouldn't have for loops because their behaviour can be reproduced with 
while loops.

But this is beside the point anyway, until you present an alternative to 
Python's current behaviour. If you do so then we can start debating the 
relative merits of the two approaches.



More information about the Python-list mailing list