dict slice in python (translating perl to python)

Discussion in 'Python' started by hofer, Sep 10, 2008.

  1. hofer

    hofer Guest

    Hi,

    Let's take following perl code snippet:

    %myhash=( one => 1 , two => 2 , three => 3 );
    ($v1,$v2,$v3) = @myhash{qw(one two two)}; # <-- line of interest
    print "$v1\n$v2\n$v2\n";

    How do I translate the second line in a similiar compact way to
    python?

    Below is what I tried. I'm just interested in something more compact.

    mydict={ 'one' : 1 , 'two' : 2 , 'three' : 3 }
    # first idea, but still a little too much to type
    [v1,v2,v3] = [ mydict[k] for k in ['one','two','two']]

    # for long lists lazier typing,but more computational intensive
    # as split will probably be performed at runtime and not compilation
    time
    [v1,v2,v3] = [ mydict[k] for k in 'one two two'.split()]

    print "%s\n%s\n%s" %(v1,v2,v3)



    thanks for any ideas
     
    hofer, Sep 10, 2008
    #1
    1. Advertising

  2. hofer

    Jon Clements Guest

    On 10 Sep, 16:28, hofer <> wrote:
    > Hi,
    >
    > Let's take following perl code snippet:
    >
    > %myhash=( one  => 1    , two   => 2    , three => 3 );
    > ($v1,$v2,$v3) = @myhash{qw(one two two)}; # <-- line of interest
    > print "$v1\n$v2\n$v2\n";
    >
    > How do I translate the second line in a similiar compact way to
    > python?
    >
    > Below is what I tried. I'm just interested in something more compact.
    >
    > mydict={ 'one'   : 1    , 'two'   : 2    , 'three' : 3 }
    > # first idea, but still a little too much to type
    > [v1,v2,v3] = [ mydict[k] for k in ['one','two','two']]
    >
    > # for long lists lazier typing,but more computational intensive
    > # as  split will probably be performed at runtime and not compilation
    > time
    > [v1,v2,v3] = [ mydict[k] for k in 'one two two'.split()]
    >
    > print "%s\n%s\n%s" %(v1,v2,v3)
    >
    > thanks for any ideas


    Another option [note I'm not stating it's preferred, but it would
    appear to be closer to some syntax that you'd prefer to use....]

    >>> from operator import itemgetter
    >>> x = { 'one' : 1, 'two' : 2, 'three' : 3 }
    >>> itemgetter('one', 'one', 'two')(x)

    (1, 1, 2)

    hth
    Jon.
     
    Jon Clements, Sep 10, 2008
    #2
    1. Advertising

  3. hofer

    B Guest

    for a long list, you could try:
    result = [mydict[k] for k in mydict]
    or [mydict[k] for k in mydict.keys()]
    or [mydict[k] for k in mydict.iterkeys()]
    this won't give you the same order as your code though, if you want them
    sorted you can use the sorted function:
    [mydict[k] for k in sorted(x)] (or sorted(x.etc))



    hofer wrote:
    > Hi,
    >
    > Let's take following perl code snippet:
    >
    > %myhash=( one => 1 , two => 2 , three => 3 );
    > ($v1,$v2,$v3) = @myhash{qw(one two two)}; # <-- line of interest
    > print "$v1\n$v2\n$v2\n";
    >
    > How do I translate the second line in a similiar compact way to
    > python?
    >
    > Below is what I tried. I'm just interested in something more compact.
    >
    > mydict={ 'one' : 1 , 'two' : 2 , 'three' : 3 }
    > # first idea, but still a little too much to type
    > [v1,v2,v3] = [ mydict[k] for k in ['one','two','two']]
    >
    > # for long lists lazier typing,but more computational intensive
    > # as split will probably be performed at runtime and not compilation
    > time
    > [v1,v2,v3] = [ mydict[k] for k in 'one two two'.split()]
    >
    > print "%s\n%s\n%s" %(v1,v2,v3)
    >
    >
    >
    > thanks for any ideas
    >
     
    B, Sep 10, 2008
    #3
  4. B wrote:
    > for a long list, you could try:
    > result = [mydict[k] for k in mydict]
    > or [mydict[k] for k in mydict.keys()]
    > or [mydict[k] for k in mydict.iterkeys()]


    and the point of doing that instead of calling mydict.values() is what?

    </F>
     
    Fredrik Lundh, Sep 10, 2008
    #4
  5. hofer

    B Guest

    Fredrik Lundh wrote:
    > B wrote:
    >> for a long list, you could try:
    >> result = [mydict[k] for k in mydict]
    >> or [mydict[k] for k in mydict.keys()]
    >> or [mydict[k] for k in mydict.iterkeys()]

    >
    > and the point of doing that instead of calling mydict.values() is what?
    >
    > </F>
    >


    It's more fun? Or if you want to sort by keys.
     
    B, Sep 10, 2008
    #5
  6. hofer

    Terry Reedy Guest

    hofer wrote:

    > Let's take following perl code snippet:
    >
    > %myhash=( one => 1 , two => 2 , three => 3 );
    > ($v1,$v2,$v3) = @myhash{qw(one two two)}; # <-- line of interest
    > print "$v1\n$v2\n$v2\n";
    >
    > How do I translate the second line in a similiar compact way to
    > python?
    >
    > Below is what I tried. I'm just interested in something more compact.


    Python does not try to be as compact as Perl. Pythoneers generally
    consider that a feature. Anyway, the second Python version is
    asymtotically as compact as the Perl code, differing only by a small
    constant number of bytes while the code size grows.

    > mydict={ 'one' : 1 , 'two' : 2 , 'three' : 3 }
    > # first idea, but still a little too much to type
    > [v1,v2,v3] = [ mydict[k] for k in ['one','two','two']]


    The initial brackets add nothing. "v1,v2,v3 =" does the same.
    >
    > # for long lists lazier typing,but more computational intensive
    > # as split will probably be performed at runtime and not compilation
    > time


    You have spent and will spend more time posting and reading than the
    equivalent extra computation time this will take with any normal
    exchange rate and computation usage.

    > [v1,v2,v3] = [ mydict[k] for k in 'one two two'.split()]


    This is a standard idiom for such things. If it bothers you, type "'one
    two two'.split()" into an interactive window and 'in a blink' get
    ['one', 'two', 'two'], which you can cut and paste into a program.

    > print "%s\n%s\n%s" %(v1,v2,v3)


    However, more that about 3 numbered variables in a Python program
    suggest the possibility of a better design, such as leaving the values
    in a list vee and accessing them by indexing.

    Terry Jan Reedy
     
    Terry Reedy, Sep 11, 2008
    #6
  7. On Thu, 11 Sep 2008 03:36:35 -0500, Nick Craig-Wood wrote:

    > As an ex-perl programmer and having used python for some years now, I'd
    > type the explicit
    >
    > v1,v2,v3 = mydict['one'], mydict['two'], mydict['two'] # 54 chars
    >
    > Or maybe even
    >
    > v1 = mydict['one'] # 54 chars
    > v2 = mydict['two']
    > v3 = mydict['two']
    >
    > Either is only a couple more characters to type.


    But that's an accident of the name you have used. Consider:

    v1,v2,v3 = section_heading_to_table_index['one'], \
    section_heading_to_table_index['two'], \
    section_heading_to_table_index['two'] # 133 characters

    versus:

    v1,v2,v3 = [section_heading_to_table_index[k] for k in
    ['one','two','two']] # 75 characters



    It also fails the "Don't Repeat Yourself" principle, and it completely
    fails to scale beyond a handful of keys.

    Out of interest, on my PC at least the list comp version is significantly
    slower than the explicit assignments. So it is a micro-optimization that
    may be worth considering if needed -- but at the cost of harder to
    maintain code.


    > It is completely
    > explicit and comprehensible to everyone, in comparison to
    >
    > v1,v2,v3 = [ mydict[k] for k in ['one','two','two']] # 52 chars
    > v1,v2,v3 = [ mydict[k] for k in 'one two two'.split()] # 54 chars


    That's a matter for argument. I find the list comprehension perfectly
    readable and comprehensible, and in fact I had to read your explicit
    assignments twice to be sure I hadn't missed something. But I accept that
    if you aren't used to list comps, they might look a little odd.



    --
    Steven
     
    Steven D'Aprano, Sep 11, 2008
    #7
  8. hofer

    hofer Guest

    Thanks a lot for all your answers.

    There's quite some things I learnt :)

    [v1,v2,v3] = ...
    can be typed as
    v1,v2,v3 = . . .

    I also wasn't used to
    map(myhash.get, ['one', 'two', 'two'])
    itemgetter('one', 'one', 'two')(x)

    I also didn't know
    print "%(one)s\n%(two)s\n%(two)s" % mydict


    The reason I'd like to have a short statement for above is, that this
    is for me basically just
    some code, to name and use certain fields of a hash in i given code
    section.

    The real example would be more like:

    name,age,country = itemgetter('name age country'.split())(x) # or any
    of my above versions

    # a lot of code using name / age / country



    thanks a gain and bye

    H
    On Sep 10, 5:28 pm, hofer <> wrote:
    > Let's take following perl code snippet:
    >
    > %myhash=( one  => 1    , two   => 2    , three => 3 );
    > ($v1,$v2,$v3) = @myhash{qw(one two two)}; # <-- line of interest
    > print "$v1\n$v2\n$v2\n";
    >
    > How do I translate the second line in a similiar compact way to
    > python?
    >
    > Below is what I tried. I'm just interested in something more compact.
    >
    > mydict={ 'one'   : 1    , 'two'   : 2    , 'three' : 3 }
    > # first idea, but still a little too much to type
    > [v1,v2,v3] = [ mydict[k] for k in ['one','two','two']]
    >
    > # for long lists lazier typing,but more computational intensive
    > # as  split will probably be performed at runtime and not compilation
    > time
    > [v1,v2,v3] = [ mydict[k] for k in 'one two two'.split()]
    >
    > print "%s\n%s\n%s" %(v1,v2,v3)
     
    hofer, Sep 11, 2008
    #8
  9. hofer

    hofer Guest

    On Sep 11, 10:36 am, Nick Craig-Wood <> wrote:
    >I'd type the explicit
    >
    > v1,v2,v3 = mydict['one'], mydict['two'], mydict['two'] # 54 chars > Either is only a couple more
    > characters to type.  It is completely
    > explicit and comprehensible to everyone, in comparison to
    >
    >   v1,v2,v3 = [ mydict[k] for k in ['one','two','two']] # 52 chars
    >   v1,v2,v3 = [ mydict[k] for k in 'one two two'.split()] # 54 chars
    >
    > Unlike perl, it will also blow up if mydict doesn't contain 'one'
    > which may or may not be what you want.
    >


    Is your above solution robust against undefined keys.
    In my example it would'nt be a problem. The dict would be fully
    populated, but I'm just curious.
     
    hofer, Sep 11, 2008
    #9
  10. hofer

    Guest

    hofer:
    > The real example would be more like:
    > name,age,country = itemgetter('name age country'.split())(x) # or any
    > of my above versions


    That solution is very clever, and the inventor smart, but it's too
    much out of standard and complex to be used in normal real code.
    Learning tricks is useful, but then in real code you have to use then
    only once in a while. A list comp is quite more easy to understand for
    Python programmers.

    Bye,
    bearophile
     
    , Sep 11, 2008
    #10
  11. hofer wrote:

    > The real example would be more like:
    >
    > name,age,country = itemgetter('name age country'.split())(x)


    ouch.

    if you do this a lot (=more than once), just wrap your dictionaries in a
    simple attribute proxy, and use plain attribute access. that is, given

    class AttributeWrapper:
    def __init__(self, obj):
    self.obj = obj
    def __getattr__(self, name):
    try:
    return self.obj[name]
    except KeyError:
    raise AttributeError(name)

    or, shorter but less obvious and perhaps a bit too clever for a
    beginning Pythoneer:

    class AttributeWrapper:
    def __init__(self, obj):
    self.__dict__.update(obj)

    you can do

    >>> some_data = dict(name="Some Name", age=123, country="SE")
    >>> some_data

    {'country': 'SE', 'age': 123, 'name': 'Some Name'}

    >>> this = AttributeWrapper(some_data)
    >>> this.name

    'Some Name'
    >>> this.age

    123
    >>> this.country

    'SE'

    and, if you must, assign the attributes to local variables like this:

    >>> name, age, country = this.name, this.age, this.country
    >>> name

    'Some Name'
    >>> age

    123
    >>> country

    'SE'
    >>>


    (the next step towards true Pythonicness would be to store your data in
    class instances instead of dictionaries in the first place, but one step
    at a time...)

    </F>
     
    Fredrik Lundh, Sep 11, 2008
    #11
  12. On Sep 11, 10:52 am, hofer <> wrote:
    > On Sep 11, 10:36 am, Nick Craig-Wood <> wrote:
    >
    > >I'd type the explicit

    >
    > >  v1,v2,v3 = mydict['one'], mydict['two'], mydict['two'] # 54 chars > Either is only a couple more
    > > characters to  type.  It is completely
    > > explicit and comprehensible to everyone, in comparison to

    >
    > >   v1,v2,v3 = [ mydict[k] for k in ['one','two','two']] # 52 chars
    > >   v1,v2,v3 = [ mydict[k] for k in 'one two two'.split()] # 54 chars

    >
    > > Unlike perl, it will also blow up if mydict doesn't contain 'one'
    > > which may or may not be what you want.

    >
    > Is your above solution robust against undefined keys.
    > In my example it would'nt be a problem. The dict would be fully
    > populated, but I'm just curious.


    If undefined keys aren't a problem, then there's a value you expect
    from them. Use

    v1,v2,v3 = [ mydict.get(k,default) for k in 'one two two'.split()]

    where default is the value you're expecting.
     
    Aaron \Castironpi\ Brady, Sep 11, 2008
    #12
  13. hofer

    MRAB Guest

    On Sep 11, 6:11 pm, Fredrik Lundh <> wrote:
    [snip]
    > (the next step towards true Pythonicness would be to store your data in
    > class instances instead of dictionaries in the first place, but one step
    > at a time...)
    >

    Surely the word is "Pythonicity"? :)
     
    MRAB, Sep 12, 2008
    #13
    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. Ethan Furman

    Python 3: dict & dict.keys()

    Ethan Furman, Jul 24, 2013, in forum: Python
    Replies:
    4
    Views:
    271
    Steven D'Aprano
    Jul 25, 2013
  2. Peter Otten

    Re: Python 3: dict & dict.keys()

    Peter Otten, Jul 24, 2013, in forum: Python
    Replies:
    1
    Views:
    113
    Neil Cerutti
    Jul 24, 2013
  3. Oscar Benjamin

    Re: Python 3: dict & dict.keys()

    Oscar Benjamin, Jul 24, 2013, in forum: Python
    Replies:
    0
    Views:
    123
    Oscar Benjamin
    Jul 24, 2013
  4. Peter Otten

    Re: Python 3: dict & dict.keys()

    Peter Otten, Jul 24, 2013, in forum: Python
    Replies:
    0
    Views:
    105
    Peter Otten
    Jul 24, 2013
  5. Skip Montanaro

    Re: Python 3: dict & dict.keys()

    Skip Montanaro, Jul 24, 2013, in forum: Python
    Replies:
    0
    Views:
    116
    Skip Montanaro
    Jul 24, 2013
Loading...

Share This Page