Perlish dictionary behavior

Alexander Schmolck a.schmolck at gmx.net
Thu Jun 3 16:40:38 EDT 2004


bit_bucket5 at hotmail.com (Chris) writes:

> One nice thing about Perl that is helpful when tallying things up by
> type is that if you increment a hash key and the key does not exist,
> Perl puts a one there.  So you can have code that does something like
> this:
>
> my %thingCounts;
> foreach my $thing(<file>)
> {
>   $thingCounts{$thing}++;
> }
>
> (I think the syntax is right, but with Perl I never am sure).
>
> In Python, this would generate a KeyError.  So you'd do something like
>
> thingCounts = {}
> for thing in file:
>   try:
>     thingCounts[thing] += 1
>   except KeyError:
>     thingCounts[thing] = 1
>
> Is there any clever way to be able to just say, like in Perl, 
> for thing in file:
>   thingCounts[thing] += 1
>
> and have it do the above?  Perhaps with a custom dictionary class or
> something?  Just wondering what that might look like.

I think what you really want is a bag (like a set, but were an item might
occur more than once). Since python doesn't have bags as yet, you either have
simply implement your own (presumably based on sets) or alternatively,
something like this (not properly tested):

    class DefaultDict(dict):
        r"""Dictionary with a default value for unknown keys."""
        def new(cls, default, noCopies=False):
            self = cls()
            self.default = default
            if noCopies:
                self.noCopies = True
            else:
                self.noCopies = False
            return self
        new = classmethod(new)
        def __getitem__(self, key):
            r"""If `self.noCopies` is `False` (default), a **copy** of
               `self.default` is returned by default.
            """              
            if key in self: return self.get(key)
            if self.noCopies: return self.setdefault(key, self.default)
            else:             return self.setdefault(key, copy.copy(self.default))

[In principle inheriting from dict is a bit untidy (since DefaultDict is not
strictly substitutable for dict), but since it should be both faster and
generally more convinient I guess it's OK]

'as




More information about the Python-list mailing list