Re: Basic list/dictionary question

Discussion in 'Python' started by Chris Rebert, Nov 11, 2009.

  1. Chris Rebert

    Chris Rebert Guest

    On Wed, Nov 11, 2009 at 4:16 AM, Daniel Jowett <> wrote:
    > Greetings,
    >
    > I'm trying to categorize items in a list, by copying them into a
    > dictionary...
    > A simple example with strings doesn't seem to work how I'd expect:
    >
    >>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
    >>>> d = {}
    >>>> d = d.fromkeys(basket, [])
    >>>> d

    > {'orange': [], 'pear': [], 'apple': [], 'banana': []}
    >>>> for fruit in basket:

    > ...     d[fruit].append(fruit)
    > ...
    >
    > No if I print d I'd EXPECT....
    >>>> d

    > {'orange': ['orange', 'orange'], 'pear': ['pear'], 'apple': ['apple',
    > 'apple'], 'banana': ['banana']}
    >
    > But what I GET is....
    >>>> d

    > {'orange': ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'], 'pear':
    > ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'], 'apple': ['apple',
    > 'orange', 'apple', 'pear', 'orange', 'banana'], 'banana': ['apple',
    > 'orange', 'apple', 'pear', 'orange', 'banana']}
    >>>>

    >
    > From what I can work out, there is only ONE list that is referenced from the
    > dictionary 4 times. Which would be because the same empty list is assigned
    > to every key in the dictionary by the "fromkeys" line. But that seems
    > seriously counter-intuitive to me...


    Python doesn't do any extra copying in most places unless you
    /explicitly/ do so yourself or ask it to; so yes, in this case, Python
    just copies references to the same object and does not copy the object
    itself.

    You'd probably be better off using a defaultdict in your particular usecase:
    http://docs.python.org/library/collections.html#collections.defaultdict

    Or and so you avoid running into it, default argument values aren't
    copied either:
    In [2]: def foo(z, a=[]):
    ...: a.append(z)
    ...: return a
    ...:

    In [3]: foo(1)
    Out[3]: [1]

    In [4]: foo(2)
    Out[4]: [1, 2]

    In [5]: foo(2)
    Out[5]: [1, 2, 2]

    In [6]: foo(3)
    Out[6]: [1, 2, 2, 3]

    In [7]: foo(4,[])
    Out[7]: [4]

    In [8]: foo(5)
    Out[8]: [1, 2, 2, 3, 5]


    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Nov 11, 2009
    #1
    1. Advertising

  2. Chris Rebert

    Ralax Guest

    On Nov 11, 8:58 pm, Chris Rebert <> wrote:
    > On Wed, Nov 11, 2009 at 4:16 AM, Daniel Jowett <> wrote:
    > > Greetings,

    >
    > > I'm trying to categorize items in a list, by copying them into a
    > > dictionary...
    > > A simple example with strings doesn't seem to work how I'd expect:

    >
    > >>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
    > >>>> d = {}
    > >>>> d = d.fromkeys(basket, [])
    > >>>> d

    > > {'orange': [], 'pear': [], 'apple': [], 'banana': []}
    > >>>> for fruit in basket:

    > > ...     d[fruit].append(fruit)
    > > ...

    >
    > > No if I print d I'd EXPECT....
    > >>>> d

    > > {'orange': ['orange', 'orange'], 'pear': ['pear'], 'apple': ['apple',
    > > 'apple'], 'banana': ['banana']}

    >
    > > But what I GET is....
    > >>>> d

    > > {'orange': ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'], 'pear':
    > > ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'], 'apple': ['apple',
    > > 'orange', 'apple', 'pear', 'orange', 'banana'], 'banana': ['apple',
    > > 'orange', 'apple', 'pear', 'orange', 'banana']}

    >
    > > From what I can work out, there is only ONE list that is referenced from the
    > > dictionary 4 times. Which would be because the same empty list is assigned
    > > to every key in the dictionary by the "fromkeys" line. But that seems
    > > seriously counter-intuitive to me...

    >
    > Python doesn't do any extra copying in most places unless you
    > /explicitly/ do so yourself or ask it to; so yes, in this case, Python
    > just copies references to the same object and does not copy the object
    > itself.
    >
    > You'd probably be better off using a defaultdict in your particular usecase:http://docs.python.org/library/collections.html#collections.defaultdict
    >
    > Or and so you avoid running into it, default argument values aren't
    > copied either:
    > In [2]: def foo(z, a=[]):
    >    ...:         a.append(z)
    >    ...:     return a
    >    ...:
    >
    > In [3]: foo(1)
    > Out[3]: [1]
    >
    > In [4]: foo(2)
    > Out[4]: [1, 2]
    >
    > In [5]: foo(2)
    > Out[5]: [1, 2, 2]
    >
    > In [6]: foo(3)
    > Out[6]: [1, 2, 2, 3]
    >
    > In [7]: foo(4,[])
    > Out[7]: [4]
    >
    > In [8]: foo(5)
    > Out[8]: [1, 2, 2, 3, 5]
    >
    > Cheers,
    > Chris
    > --http://blog.rebertia.com


    Usefull!
     
    Ralax, Nov 11, 2009
    #2
    1. Advertising

  3. Ralax wrote:
    > On Nov 11, 8:58 pm, Chris Rebert <> wrote:
    >> In [2]: def foo(z, a=[]):
    >> ...: a.append(z)
    >> ...: return a
    >> ...:
    >>
    >> In [3]: foo(1)
    >> Out[3]: [1]
    >>
    >> In [4]: foo(2)
    >> Out[4]: [1, 2]
    >>
    >> In [5]: foo(2)
    >> Out[5]: [1, 2, 2]
    >>
    >> In [6]: foo(3)
    >> Out[6]: [1, 2, 2, 3]
    >>
    >> In [7]: foo(4,[])
    >> Out[7]: [4]
    >>
    >> In [8]: foo(5)
    >> Out[8]: [1, 2, 2, 3, 5]

    >
    > Usefull!


    I think Chris post was meant as a warning, but yes, it is useful
    sometimes. Here's a less error-prone version:

    >>> def bar():

    .... def foo(z, a=[]):
    .... a.append(z)
    .... return a
    .... return foo
    ....
    >>> f = bar()
    >>> f(1)

    [1]
    >>> f(2)

    [1, 2]
    >>> g = bar()
    >>> g(3)

    [3]
    >>> g(4)

    [3, 4]

    Regards,
    Mick.
     
    Mick Krippendorf, Nov 11, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ilias Lazaridis
    Replies:
    6
    Views:
    463
    Ilias Lazaridis
    Feb 21, 2006
  2. james_027
    Replies:
    1
    Views:
    349
    Marc 'BlackJack' Rintsch
    Aug 22, 2007
  3. Navkirat Singh
    Replies:
    6
    Views:
    3,266
    Navkirat Singh
    Jul 29, 2010
  4. Chris Rebert
    Replies:
    0
    Views:
    561
    Chris Rebert
    Jul 29, 2010
  5. Fox

    dictionary within dictionary

    Fox, Mar 8, 2005, in forum: ASP General
    Replies:
    5
    Views:
    205
    Michael D. Kersey
    Mar 13, 2005
Loading...

Share This Page