A more concise way to write this?

Is there a more concise way to write this in Python?

cur = aToListB.get(elementA, [])
cur.append(listB)
aToListB[elementA] = cur
   

In Perl, for example, I could express this in one line:

push( @{$aToListB{elementA}}, listB )


Thanks.
BerkeleyJeffAsked:
Who is Participating?
 
RichieHindleCommented:
Yes, you can, using the rather oddly-named setdefault() function:

   aToListB.setdefault(elementA, []).append(listB)

setdefault() says "return the value for this key, and if it's not already there, set it to this value first."

Here's a test script:

def Jeff(aToListB, elementA, listB):
    cur = aToListB.get(elementA, [])
    cur.append(listB)
    aToListB[elementA] = cur
    return aToListB

def Richie(aToListB, elementA, listB):
    aToListB.setdefault(elementA, []).append(listB)
    return aToListB

for test in Jeff, Richie:
    print test({}, 'one', 1)           # Empty dict
    print test({'one': []}, 'one', 1)  # dict with empty value
    print test({'one': [1]}, 'one', 2) # dict with existing value


The script prints:

{'one': [1]}
{'one': [1]}
{'one': [1, 2]}
{'one': [1]}
{'one': [1]}
{'one': [1, 2]}

0
 
BerkeleyJeffAuthor Commented:
Thanks! That's exactly what I was looking for.

setdefault certainly is an odd name. I think that they should just call it 'set', to make clear its role as the counterpart of 'get'. Or perhaps get should instead be called getdefault.

I'm a bit confused by the return type of setdefault. It must be returning aToListB by reference, rather than by value, since otherwise  'append' wouldn't be mutating aToListB. But I thought arguments to functions were passed by value in Python, rather than being passed by reference.
0
 
peprCommented:
The doc says (2.3.8 Mapping Types -- classdict)

   "a.setdefault(k[, x])     ...   a[k] if k in a, else x (also setting it)

    setdefault() is like get(), except that if k is missing, x is both returned and inserted into the dictionary as the value of k. x defaults to None."

In Python, every variable is a named reference, never the value. When name is used as a function argument, the reference is copied and the copy is bound to the internal name inside the function. When assigning the variable, you are always copying the reference that is then bound to the name of the variable. But the name may be later rebound to another reference.
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
RichieHindleCommented:
Here's my version of what pepr said:

There is no "pass by reference" or "pass by value" in Python, only "pass by object reference", along with the fact that some objects are mutable and some are not.  So passing the number 3 to a function passes a reference to the number 3.  You can't change the number 3, so in this case Python behaves in a "pass by value" kind of way.  If you pass a list to a function, that can be changed, so Python behaves in a "pass by reference" way.  But really both are the same - in both cases, a reference to an object is being passed.  The only difference is that one object is mutable and the other isn't.

Names in Python are references to objects.  If you say "x = 3" you are defining a named reference to the number 3.  If you then pass x to a function, you are passing a reference to the number 3.  The function doesn't know that the reference was originally called x, and can do nothing to the name x.  If you say "x = [3]", you are defining a named reference to a list which refers to the number 3.  If you pass x to a function, you are passing a reference to that list.  Because lists are mutable, the list can be changed by that function.  The function can't change the fact that x points to that list, but it can change the list itself.

You should read this: http://effbot.org/zone/python-objects.htm  Pay particular attention to the "Introduction" section.  8-)
0
 
peprCommented:
... and to add. In fact, names does not matter. Everything important is related to the objects (and their classes). References can exist without a name (for example when stored inside a list). References are the unambiguous identifications plus the built-in behaviour of the interpreter (how the references should be treated). Current CPython implements the identification as the memory address where the objects sits.

A name is always bound to an object. The binding of the name to the object is done via some of the internal dictionaries accessible via built-in functions locals() and globals(). The key is the name, the value is the reference.
0
 
BerkeleyJeffAuthor Commented:
I've got a similar question about setdefault, which I posted here:

http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21929043.html

I would appreciate any help you can offer.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.