[Python-Dev] Re: Sets: elt in dict, lst.include

Tim Peters tim.one@home.com
Mon, 29 Jan 2001 20:39:17 -0500


[Guido]
> I did a less sophisticated count but come to the same conclusion:
> iterations over items() are (somewhat) more common than over keys(),
> and values() are 1-2 orders of magnitude less common.  My numbers:
>
> $ cd python/src/Lib
> $ grep 'for .*items():' *.py | wc -l
>      47
> $ grep 'for .*keys():' *.py | wc -l
>      43
> $ grep 'for .*values():' *.py | wc -l
>       2

I like my larger sample and anal methodology better <wink>.  A closer look
showed that it may have been unduly biased by the mass of files in
Lib/encodings/, where

encoding_map = {}
for k,v in decoding_map.items():
    encoding_map[v] = k

is at the end of most files (btw, MAL, that's the answer to your question:
people would expect "the same" ordering you expected there, i.e. none in
particular).

> ...
> I don't much value to the readability argument: typically, one will
> write "for key in dict" or "for name in dict" and then it's obvious
> what is meant.

Well, "fiddlesticks" comes to mind <0.9 wink>.  If I've got a dict mapping
phone numbers to names, "for name in dict" is dead backwards.

    for vevent in keydefs.keys():
    for x in self.subdirs.keys():
    for name in lsumdict.keys():
    for locale in self.descriptions.keys():
    for name in attrs.keys():
    for func in other.top_level.keys():
    for func in target.keys():
    for i in u2.keys():
    for s in d.keys():
    for url in self.bad.keys():

are other cases in the CVS tree where I don't think the name makes it
obvious in the absence of ".keys()".

But I don't personally give any weight to whether people can guess what
something does at first glance.  My rule is that it doesn't matter, provided
it's (a) easy to learn; and (especially), (b) hard to *forget* once you've
learned it.  A classic example is Python's "points between elements"
treatment of slice indices:  few people guess right what that does at first
glance, but once they "get it" they're delighted and rarely mess up again.

And I think this is "like that".

> ...
> But here's my dilemma.  "if (k, v) in dict" is clearly useless (nobody
> has even asked me for a has_item() method).

Yup.

> I can live with "x in list" checking the values and "x in dict"
> checking the keys.  But I can *not* live with "x in dict" equivalent
> to "dict.has_key(x)" if "for x in dict" would mean
> "for x in dict.items()".

That's why I brought it up -- it's not entirely clear what's to be done
here.

> I also think that defining "x in dict" but not "for x in dict" will
> be confusing.
>
> So we need to think more.

The hoped-for next step indeed.

> How about:
>
>     for key in dict: ...		# ... over keys
>
>     for key:value in dict: ...		# ... over items
>
> This is syntactically unambiguous (a colon is currently illegal in
> that position).

Cool!  Can we resist adding

    if key:value in dict

for "parallelism"?  (I know I can ...)  2/3rd of these are marginally more
attractive:

    for key: in dict:    # over dict.keys()
    for :value in dict:  # over dict.values()
    for : in dict:       # a delay loop

> This also suggests:
>
>     for index:value in list: ...	# ... over zip(range(len(list), list)
>
> while doesn't strike me as bad or ugly, and would fulfill my brother's
> dearest wish.

You mean besides the one that you fry in hell for not adding "for ...
indexing"?  Ya, probably.

> (And why didn't we think of this before?)

Best guess:  we were focused exclusively on sequences, and a colon just
didn't suggest itself in that context.  Second-best guess:  having finally
approved one of these gimmicks, you finally got desperate enough to make it
work <wink>.

ponderingly y'rs  - tim