default behavior

wheres pythonmonks wherespythonmonks at gmail.com
Sat Jul 31 01:02:47 EDT 2010


>
> Hint -- what does [].append(1) return?
>

Again, apologies from a Python beginner.  It sure seems like one has
to do gymnastics to get good behavior out of the core-python:

Here's my proposed fix:

 m['key'] = (lambda x: x.append(1) or x)(m.get('key',[]))

Yuck!  So I guess I'll use defaultdict with upcasts to dict as needed.

On a side note:  does up-casting always work that way with shared
(common) data from derived to base?  (I mean if the data is part of
base's interface, will  b = base(child) yield a new base object that
shares data with the child?)

Thanks again from a Perl-to-Python convert!

W


On Fri, Jul 30, 2010 at 11:47 PM, Steven D'Aprano
<steve at remove-this-cybersource.com.au> wrote:
> On Fri, 30 Jul 2010 08:34:52 -0400, wheres pythonmonks wrote:
>
>> Sorry, doesn't the following make a copy?
>>
>>>>>> from collections import defaultdict as dd x = dd(int)
>>>>>> x[1] = 'a'
>>>>>> x
>>> defaultdict(<type 'int'>, {1: 'a'})
>>>>>> dict(x)
>>> {1: 'a'}
>>>
>>>
>>>
>>
>> I was hoping not to do that -- e.g., actually reuse the same underlying
>> data.
>
>
> It does re-use the same underlying data.
>
>>>> from collections import defaultdict as dd
>>>> x = dd(list)
>>>> x[1].append(1)
>>>> x
> defaultdict(<type 'list'>, {1: [1]})
>>>> y = dict(x)
>>>> x[1].append(42)
>>>> y
> {1: [1, 42]}
>
> Both the defaultdict and the dict are referring to the same underlying
> key:value pairs. The data itself isn't duplicated. If they are mutable
> items, a change to one will affect the other (because they are the same
> item). An analogy for C programmers would be that creating dict y from
> dict y merely copies the pointers to the keys and values, it doesn't copy
> the data being pointed to.
>
> (That's pretty much what the CPython implementation does. Other
> implementations may do differently, so long as the visible behaviour
> remains the same.)
>
>
>
>> Maybe dict(x), where x is a defaultdict is smart?  I agree that a
>> defaultdict is safe to pass to most routines, but I guess I could
>> imagine that a try/except block is used in a bit of code where on the
>> key exception (when the value is absent)  populates the value with a
>> random number.  In that application, a defaultdict would have no random
>> values.
>
> If you want a defaultdict with a random default value, it is easy to
> provide:
>
>>>> import random
>>>> z = dd(random.random)
>>>> z[2] += 0
>>>> z
> defaultdict(<built-in method random of Random object at 0xa01e4ac>, {2:
> 0.30707092626033605})
>
>
> The point which I tried to make, but obviously failed, is that any piece
> of code has certain expectations about the data it accepts. If take a
> function that expects an int between -2 and 99, and instead decide to
> pass a Decimal between 100 and 150, then you'll have problems: if you're
> lucky, you'll get an exception, if you're unlucky, it will silently give
> the wrong results. Changing a dict to a defaultdict is no different.
>
> If you have code that *relies* on getting a KeyError for missing keys:
>
> def who_is_missing(adict):
>    for person in ("Fred", "Barney", "Wilma", "Betty"):
>        try:
>            adict[person]
>        except KeyError:
>            print person, "is missing"
>
> then changing adict to a defaultdict will cause the function to
> misbehave. That's not unique to dicts and defaultdicts.
>
>
>
>> Besides a slightly different favor, does the following have applications
>> not covered by defaultdict?
>>
>> m.setdefault('key', []).append(1)
>
> defaultdict calls a function of no arguments to provide a default value.
> That means, in practice, it almost always uses the same default value for
> any specific dict.
>
> setdefault takes an argument when you call the function. So you can
> provide anything you like at runtime.
>
>
>> I think I am unclear on the difference between that and:
>>
>> m['key'] = m.get('key',[]).append(1)
>
> Have you tried it? I guess you haven't, or you wouldn't have thought they
> did the same thing.
>
> Hint -- what does [].append(1) return?
>
>
> --
> Steven
> --
> http://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list