From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Wed, 28 Apr 1999 11:13:28 -0400 (EDT)
Subject: try vs. has_key()
In-Reply-To: <aahzFAvFCz.3Lr@netcom.com>
References: <aahzFAM4oJ.M7M@netcom.com>
	<yWOT2.6007$8m5.9320@newsr1.twcny.rr.com>
	<Pine.SUN.3.95-heb-2.07.990423140345.21577A-100000@sunset.ma.huji.ac.il>
	<7g51q6$1pt$1@vvs.superst.iae.nl>
	<aahzFAvFCz.3Lr@netcom.com>
Message-ID: <14119.8145.293039.667256@bitdiddle.cnri.reston.va.us>
Content-Length: 2011
X-UID: 212                                                  

>>>>> "AM" == Aahz Maruch <aahz at netcom.com> writes:

  AM> It appears that the second parameter for get() (to specify a
  AM> value different from None when the key is not found) is new to
  AM> 1.5.2.  In 1.5.1 you still have to do the following:

That's not correct.  The optional second argument for get has been
around since get was introduced, which was before the release of 1.5
final.  (You check the CVS log for dictobject.c for confirmation :-).
If you use get, you can always specify a default value.

This thread seems to have included a lot of code that misuses
dictionaries and other built-in types, which is probably why you
concluded that get changed between 1.5.1 and 1.5.2.

I think the confusion started when the following bits of code were
posted: 

    d={}
    for word in words:
        d[word]=d.get(word, 0)+1

The above part is just fine -- an efficient way to count words.

    d={}
    for word in words:
        first_two=word[:2]
        d[first_two]=d.get(first_two, []).append(word)

This second bit doesn't work because the append method on list objects 
returns None.  As a result, the first time a new value for first_two
appears None will be assigned to that key in the dictionary.  The
second time that value of first_two shows up, None will be returned by 
d.get.  Then the code will raise an AttributeError, because None
doesn't have an append method.

The following code would be correct:

    d={}
    for word in words:
        first_two=word[:2]
        d[first_two]= temp = d.get(first_two, [])
        temp.append(word)

It would be less efficient, however, than the following:

    d={}
    for word in words:
        first_two=word[:2]
	if d.has_key(first_two):
            d[first_two].append(word)
        else:
            d[first_two] = [word]

(And as Barry pointed out earlier in the thread, depending on how
frequently you expect has_key to return true, you may want to use
try/except instead.  See http://www.python.org/~bwarsaw/ecshort.pdf.)

Jeremy




