[Python-Dev] Default constructor values (Re: [Python-checkins] python/dist/src/Doc/lib libfuncs.tex,1.134,1.135)

M.-A. Lemburg mal@lemburg.com
Fri, 13 Jun 2003 10:34:49 +0200


Alex Martelli wrote:
> On Friday 13 June 2003 09:40 am, M.-A. Lemburg wrote:
>    ...
>>>>If you really happen to have a need for this, why can't you
>>>>introduce factory functions which take care of your particular
>>>>use case ? I don't think it's common enough to risk accidental
>>>>progamming errors in other user's code.
>>>
>>>Marc, you haven't shown why it's so bad either, so please shut up.
>>
>>I beg your pardon: Just look at the last sentence in my reply. It is
>>you that hasn't shown a single qualified use case for this "feature".
>>You also haven't shown why the defaults you have chosen were picked
>>and what the reasoning was.
> 
> It appears to me that both the pluses and minuses for this design choice
> are so small as not to justify the intensity of the debate (but I may be
> missing some subtext).  As long as the behavior of such built-in types
> as str, int, long, bool, float &c is consistent -- either all of them can be
> called without arguments (each returning a "canonical 'zero' instance" of
> the respective type), or none of them can -- I'd be (abstractly) happy.  As
> it happens some of them had this minor feature at least as far back as
> 2.2.2 (earlier I think) so it seems obvious to me that it shouldn't be taken
> away in 2.3 (what a gratuitous incompatibility that would be!), and that the
> debate is purely theoretical.
> 
> As for use cases -- I have not had one in real life in Python (so far), and
> indeed if any of the built-in types didn't respect the rule I believe no use
> case could present itself.  I did have uses for a very similar feature of C++
> types (in C++ templates) and I did note Andrew Koenig speaking up on
> this thread about the same thing.  The parallels are not exact, I think.  One
> example is making a "canonical type-matching representation" of e.g. a
> tuple:
>     canonical_tuple = tuple( [ type(x)() for x in original_tuple ] )
> to be used e.g. as a dictionary key for multiple dispatch based on types.
> In Python, you have some alternatives to this approach, e.g. relying on
> the fact that types are first-class objects:
>     types_tuple = tuple( [ type(x) for x in original_tuple ] )
> 
> There may still be advantages in using the "tuple of typical instances"
> rather than the tuple of types -- minor advantages, to be sure, but then
> the "error risk" that seems to be the only disadvantage to offset it is
> also quite minor in itself.  For example, consider:
> 
> 
>>>>original_tuple = (1, 2.0, 3L, '4', u'5', False)
>>>>canonical_tuple = tuple([type(x)() for x in original_tuple])
>>>>types_tuple = tuple([type(x) for x in original_tuple])
>>>>pick_can = pickle.dumps(canonical_tuple, 2)
>>>>pick_typ = pickle.dumps(types_tuple, 2)
>>>>len(pick_can)
> 
> 32
> 
>>>>len(pick_typ)
> 
> 129
> 
> 
> Pickling the canonical-tuple rather than the types-tuple saves about 3/4
> the space.  Roughly similar ratios can be seen if what one wants is a
> readable string representation of the canonical or types tuple:
> 
> 
>>>>len(str(canonical_tuple))
> 
> 28
> 
>>>>len(str(types_tuple))
> 
> 92
> 
> 
> 
> So, I think some use cases do exist for the general-ish rule "whenever
> it makes some sense, a type is callable without arguments and when so
> called returns the one instance of that type which evaluates to false".
> 
> That 'false instance' then becomes the "default, or rather, canonical"
> instance of the type, and can be used to 'stand for the type' in cases such
> as the above tuples.  Given any instance of the unknown type the canonical
> instance can be obtained as type(x)().
> 
> Other uses involve e.g. simplifying a generator (or other callable) that takes 
> a factory function and may call it without arguments: in some cases this
> will let you pass the type object directly, e.g. int, rather than making up a
> simple factory such as lambda: 0.  Tiny and marginal advantages, to be
> sure.  But the claimed disadvantage also looks tiny and marginal to me.

Thanks, Alex. At least you're giving a reasonable analysis of the
idea behind the default constructor values.

I can see your point and given that we can't revert to the non-default
value due to the fact that e.g. int() and str() already behave like
this in Python2.2, I withdraw my request. No idea, why Guido couldn't
have come up with a similar explanation or a simple "hey, at the time
I thought it was better this way". That ignorace probably caused the
heat on my side, not the subject itself.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Software directly from the Source  (#1, Jun 13 2003)
 >>> Python/Zope Products & Consulting ...         http://www.egenix.com/
 >>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/
________________________________________________________________________
EuroPython 2003, Charleroi, Belgium:                        11 days left