PEP 285: Adding a bool type
Ype Kingma
ykingma at accessforall.nl
Mon Apr 8 18:23:49 EDT 2002
Alex,
> > The language spec does not specify the type of the index or key
> > argument to __getitem__.
>
> It does for sequences (int and slice only) and for dictionaries (any
> hashable) but not for other mappings (each mapping define its
> own rules: something like "only a string is accepted" is quite
> common in various mappings implemented in the standard
> library, for example).
I concluded that the type of the key argument is not specified from:
http://www.python.org/doc/current/ref/sequence-types.html :
__getitem__(self, key)
Called to implement evaluation of self[key]. For sequence types, the accepted keys
should be integers and slice objects.
Note that the special interpretation of negative indexes (if the class wishes to
emulate a sequence type) is up to the __getitem__() method. If key is of an
inappropriate type, TypeError may be raised; if of a value outside the set of
indexes for the sequence (after any special interpretation of negative values),
IndexError should be raised. Note: for loops
expect that an IndexError will be raised for illegal indexes to allow proper
detection of the end of the sequence.
End of quote.
> >> - testing membership with aset.has_key(item),
> >> or:
> >> - indicating membership with aset[item] = 1, then
> >> - testing membership with aset.get(item, 0)
> >>
> >> Why would you think this is "rare"? It's common currency. How many tens
> >> of thousands of lines of python have you written, reviewed, or
> >> maintained, that you presume to teach me what is common and what is rare
> >> in python "as she is spoken", pray?
> >
> > In how many of these cases would the 'item' key actually be confused
> > when it could be either a bool or an int? So far you failed to convince me
> > that this is not a rare case.
>
> What does it matter what type the item is? has_key must now return
Because that is where the confusion would lead to problems when
True and 1 are considered different keys.
> a Boolean, while the get idiom that always was equivalent to it must
> keep returning int. Any existing code that has tests coded both ways,
> for ANY type of item, will return "mixed" Booleans and int's. Modern
> equivalent idiom "item in aset" also returns Boolean, but THAT is quite
> likely rare since it only became possible in Python 2.2. Still, where 2.2
> was accepted as the used language version, whenever the get idiom
> was used I refactored it into the 'in' operator on code I was revising
> anyway (but not on parts of code I wasn't revising) -- clearer, more
> concise, AND faster... irresistible (the "one obvious way to do it", once
> it became acceptable).
Such mixing of bool and int would be handled in the special methods of
the bool and int classes, eg. the __add__ method of the bool class
would use the appropriate integer value when both operands are bools.
> > Even though I don't see the relevance of the second question
> > the answer is: a few, and I'm not teaching here, I'm explaining
> > my opinion.
>
> Based on WHAT experience of Python, that's what I'm asking --
> maintenance responsibility for how many tens of thousands of lines,
A few.
> etc. How can you have a sound opinion on what is rare or frequent if
> not on the basis of some reasonably representative sample?
The opinion comes from my intuition that most of the work on mixed bool
and other types would be done in a backwards compatible way by the special
methods of the standard types.
For example, assuming pure bool True and False:
True + True --> 2 # done by the __add__ method bool
5 * False --> 0 # by __mul__ of int, or by __rmul__ of bool
True - 1 --> 0 # by __sub__ of bool, or by __rsub__ of int.
And even:
'01'[True] --> '1' # done by __getitem__ of string.
As I said earlier, I don't like this behaviour, but I am
in favour of PEP 285, and I accept this.
However, dictionary indexing can be problematic as I indicated above.
For example when indicating membership with aset[item] = 1,
this would break:
m1 = aset.has_key(item)
someDict[m1] = value1
m2 = aset.get(item, 0)
someDict[m2] = value2
To break, it not only needs _both_ styles of membership testing
to occur in the same program, but also the results of both
styles should be used to index a dictionary.
How often are the direct results of both styles of tests used to
index a dictionary?
> >> > 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.
> >>
> >> Old-style only will do perfectly well, since lots of extremely common
> >> idioms therein (a<b, d.has_key(k), x in y, and so on) change return
> >> values silently. Neither any mistake nor any 'together' is needed,
> >> unless you're somehow trying to imply that anybody coding some kind
> >> of "advanced" (?!) construct such as "a<b" was using "new style code"
> >> unwittingly years ago...
> >
> > By new style I meant explicit use of True/False.
>
> So do I: and there is absolutely no "explicit use of True/False" in any
> of the several expressions I enumerted, nor the many more whose
> return type change silently from int to Boolean. "True and 1 are used
> interchangeably" in any existing function that can return any of these
> expressions OR an explicit 0 or 1, as in:
I meant this to be limited to the context of indexing dictionary
like objects. Somehow that context was lost :(
> def isValueAtIndex(alist, anindex, avalue):
> if -len(alist)<=anindex<len(alist):
> return alist[ainindex] == avalue
> else:
> return 0
>
> or equivalently and more Pythonically:
>
> def isValueAtIndex(alist, anindex, avalue):
> try: return alist[ainindex] == avalue
> except IndexError: return 0
>
> There is absolutely no programmer mistake here, nor any use of old
> style and new style code together. Yet such existing code may very
> well return int or Boolean interchangeably _because the return type
> of very common operations has changed silently in 2.3_ ... !!!
Which I expect to be handled well by other special methods, see above.
> > As for "advanced (?!): I don't have a time machine.
>
> So you'll have to admit that claiming "interchangeable return of int
> or Boolean" can only be caused by mistakes or "mixing old and
> new style" was a wildly unfounded assertion, yes?
Again the context was lost.
> >> > In the pure case an int() call would not be needed at all:
> >>
> >> But to check whether it's needed or not, a type-check would be
> >> needed, and that IS a substantial slow-down. You don't seem to
> >
> > If it's not needed at all, there is also no need for the check.
>
> How do you *KNOW* whether to check or not, without a check?
Since bool would be normally hashable and there would be no
need to 'cast' True/False to 1/0, the __getitem__ method of dict
would not need to treat bool as a special case.
> > I am not talking about an actual implementation.
> > I'm talking about a specification, while trying to keep an eye on
> > implementABILITY.
> > Since you didn't say it cannot be done, I'm actually encouraged.
>
> It IS quite possible to implement a language where the semantics
> of, say, + and - operators, are switched in any source line which has a
> prime number of characters. It IS totally absurd, but clearly feasible.
>
> Why such technical feasibility would encourage anybody to consider
> such absurdities is beyond me, but please feel free to go ahead and
> implement such a beauty. It will still be less absurd and abstruse
> than your cherished "implementable" specification, anyway.
>
Most of the work to handle mixed bool and other types I meant to be done
in a backwards compatible way.
Regards,
Ype
P.S.
Deprecation of mixed type dictionary indexing could be done in phases:
a. deprecate indexing of standard dictionaries using both PEP 285 bool
and int keys.
b. introduce pure bool and emulate the 1/0 behaviour of pure
True and False. This takes the performance hit for the typecheck
on bool and the cast to 1/0 for __getitem__ (and friends) of
standard dicts.
c. end the deprecation by removing the this typecheck.
Phase b. would off course be as short as possible.
Some other interesting code I remember reading about would also
be involved in deprecation:
type(b) == type(1) # breaks in 2.3?, ie. already deprecated?
# breaks when removing the subtype relation between bool and int:
isinstance(b, type(1))
--
email at xs4all.nl
More information about the Python-list
mailing list