a clean way to define dictionary
Michele Simionato
mis6 at pitt.edu
Thu Jun 19 17:32:19 EDT 2003
Alexander Schmolck <a.schmolck at gmx.net> wrote in message news:<yfswufi6j86.fsf at black132.ex.ac.uk>...
> mis6 at pitt.edu (Michele Simionato) writes:
>
> Well, your timings are not all that meaningful because your code does nothing
> and you only instance creation and not item access (which obviously also needs
> to be overridden with python code).
This was on purpose, I wanted to measure the slowdown due to "pure"
subclassing, i.e. without doing anything to __getattr__ and __setattr__.
> Anywhere, here is a real DefaultDict class
> and some ad hoc timings, which show *10* fold slowdown for creation and 4 fold
> for item access (the copy.copy call seems harmless performance-wise).
>
> class DefaultDict(dict):
> r"""Dictionary with a default value for unknown keys."""
> def __init__(self, default, noCopies=False):
> self.default = default
> if noCopies:
> self.noCopies = True
> else:
> self.noCopies = False
> 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))
>
> timings for python2.2
>
> In [58]: timeCall(nTimes, 10000, dict)
> Out[58]: 0.018522977828979492
>
> In [59]: timeCall(nTimes, 10000, DefaultDict, 1)
> Out[59]: 0.11231005191802979
>
> In [47]: timeCall(nTimes, 10000, {'foo':0}.__getitem__, 'foo')
> Out[47]: 0.012811064720153809
>
> In [48]: timeCall(nTimes, 10000, DefaultDict(1).__getitem__, 'foo')
> Out[48]: 0.045480012893676758
>
> In [65]: timeCall(nTimes, 10000, DefaultDict(1,0).__getitem__, 'foo')
> Out[65]: 0.04657900333404541
>
>
> What are your results for instance creation with this class? Maybe 2.3 is
> noticeably faster?
>
>
> 'as
I should perform a series of tests; anyway, some simple experiment
with attribute access gives me a slowdown of ~14 times. Quite a lot.
However, my point was that you can bypass the Python 2.3 change in the
dictionary constructor signature by overriding __new__ and *not* changing
__getattr__. In this way, you don't have a performance problem.
Of course, if you override __getattr__, there is an issue, but the
issue would be the same with Python 2.2.
I am curious to test the difference between Python 2.2 and 2.3;
I will look at the instance creation time too, but this is less
important than the access time, since typically I create a dictionary
only once.
Michele
More information about the Python-list
mailing list