PEP 285: Adding a bool type

Ype Kingma ykingma at accessforall.nl
Fri Apr 5 17:26:56 EST 2002


Alex,


> >> This is the Python LANGUAGE we know and love -- the LANGUAGE
> >> Reference says so, and us Language Lawyers know that.  You want to
> >> change Python, that's one thing.  But don't tell us that this part of the
> >> Language Reference "is not part of the python language".
> >
> > I do not want to change that part of the language. I tried to
> > say that the backward compatible 1/0 behaviour and
> > the Something/Nothing behaviour can be implemented in the special methods
> > of the standard types, even when a non int-a-new-hat bool would be added
> > to the language.
> 
> Even if having to modify the __getitem__, __setitem__, __delitem__ (at
> the least) of a zillion user-defined types out there was feasible (and it's
> not), I think this would not fully exhaust, as I indicated.

The users writing such code were knowingly taking a risk by using
a name that starts with a double underscore. For these cases I think
deprecation is quite acceptable.

(Off course one could simply iirc :1,$s/\<__//g in all concerned code,
but that would cause too many other problems.)

> I use slices in every sequence-like type I code -- a slice object
> is what gets passed to my __getitem__ (etc) methods when
> client code uses myobject[3:] or whatever (special methods
> __getslice__ etc are deprecated for new objects, although for
> backwards compatibility they're still used if present, and quite
> unfortunately list &c still use them).  My __getitem__ &c need
> to know whether they're called with an index that has .start
> and .stop attributes (I feature-test for those, obviously, NOT
> typetest for slice!) or with an index that is a number.  I feel
> absolutely no need to know whether an argument passed to
> my object's method comes from -- and on the other side of
> things, to know whether my object is being tested for truth,
> why, I already have the (unfortunately named) __nonzero__.

When the object passed to your __getitem__ method does not
have .start and .stop attributes you could simply call int()
on it from within your __getitem__ implementation.
But you would only need to do this in certain cases, see below.

> > Indexing a dict with both int and bool keys might involve some confusion
> > when True is not 1 anymore. This case should be rare, however.
> 
> Why should it be rare?  All hashables are used uniformly as keys
> into dictionaries.

It should be rare because the confusion would only occur when both
True and 1 are used as keys and they are intended to be the same key.
That should only happen when True and 1 are used interchangeably,
which might happen by programmer mistake or by using 
old (1/0) and new (True/False) style code together.

> > For standard types, ie. normal dictionaries there is no problem since
> > one can simply add the int() method call in the implementation of
> > __getitem__ of the standard dictionary for backwards compatibility.
> 
> You propose a substantial slow-down of standard dictionaries "for
> backwards compatibility" against an incompatibility that need never
> be introduced in the first place -- you can't "simply add the int()
> method call", you first have to typetest against boolean on EVERY
> dictionary access to know if the "int()" kludge is needed at all (you
> can't just call int() on EVERY key without breaking a megazillion
> lines of code -- i hope you realize that? -- and if you could that
> would be a slow-down too).  I don't think you realize at all how
> CRUCIAL dictionary look-up performance is to Python.  The number
> of dictionary accesses is huge in every real Python program.  If there
> is one thing that MUST be always optimized, that's the one.
> 
> The incompatibility is needless: apart from un-engineeringly yearnings
> for "purity" (which, in Python, is trumped by pragmatics) there's no
> reason for hash(True) to differ from 1, and True==1 is similarly not
> a problem at all.  Easiest would be not to distinguish booleans from
> ints at all, second easiest, as the PEP proposes, to make booleans
> a subclas of ints, but even without the latter pragmatic fix a sensible
> strategy would still be feasible.  Slowing down all dictionary access
> is NOT a sensible strategy, nor acceptable at all.
> 
> Slowing down all list accesses as you want to do is not quite as
> horrible, but still a pretty bad move.  What Python most needs right
> now is a bit more attention to performance issues, NOT slow-downs
> in its core to satisfy some people's desires for "purity".

The slowdown would be there for backwards compatibility only.
In the pure case an int() call would not be needed at all: 
no one would index a list directly with a bool and a dict might repr as:

{True:'Used to be like one', 1:'The only one'}

ie. True and 1 would be different keys.
When adding the int() call to the __setitem__ method of the standard
dicts for backward compatibility the dict shown above would only a have
a single key 1 and the value would be the last value put there.

> > User code trying to implement a dictionary will need a similar
> > fix as I pointed out above. I can only hope there is no more breakage in
> > user code.
> 
> "only hope" is not acceptable in this context.  Fortunately, we can
> do better than that (and I'm confident that the unacceptability of
> slowing down dictionaries and lists is quite obvious to decision
> makers in this case, so I don't fear it will happen).

I'm still putting my hopes on deprecation (as above) after PEP 285 enters
into force. During the deprecation phase with non int bools such cases
could be warned for eg. by a special verion of int() that would also cause
a slowdown, and after the deprecation a pure version with normal speed
would remain.

Regards,
Ype


P.S. I havn't followed the change of behaviour of the / operator in detail,
but wasn't/isn't this done using a deprecation period with warnings, too?

-- 
email at xs4all.nl



More information about the Python-list mailing list