6

Is there a way to efficiently concatenate str and list?

inside = [] #a list of Items

class Backpack:
    def add(toadd):
        inside += toadd

print "Your backpack contains: " #now what do I do here?
SuperCheezGi
  • 857
  • 3
  • 11
  • 19
  • 2
    This is a side comment, but: you almost certainly don't want a class that uses a global variable for storage, and you also probably want `add` to take a `self` param… – abarnert Nov 02 '12 at 23:10

2 Answers2

9

It sounds like you're just trying to add a string to a list of strings. That's just append:

>>> inside = ['thing', 'other thing']
>>> inside.append('another thing')
>>> inside
['thing', 'other thing', 'another thing']

There's nothing specific here to strings; the same thing works for a list of Item instances, or a list of lists of lists of strings, or a list of 37 different things of 37 different types.

In general, append is the most efficient way to concatenate a single thing onto the end of a list. If you want to concatenate a bunch of things, and you already have them in a list (or iterator or other sequence), instead of doing them one at a time, use extend to do them all at once, or just += instead (which means the same thing as extend for lists):

>>> inside = ['thing', 'other thing']
>>> in_hand = ['sword', 'lamp']
>>> inside += in_hand
>>> inside
['thing', 'other thing', 'sword', 'lamp']

If you want to later concatenate that list of strings into a single string, that's the join method, as RocketDonkey explains:

>>> ', '.join(inside)
'thing, other thing, another thing'

I'm guessing you want to get a little fancier and put an "and" between the last to things, skip the commas if there are fewer than three, etc. But if you know how to slice a list and how to use join, I think that can be left as an exercise for the reader.

If you're trying to go the other way around and concatenate a list to a string, you need to turn that list into a string in some way. You can just use str, but often that won't give you what you want, and you'll want something like the join example above.

At any rate, once you have the string, you can just add it to the other string:

>>> 'Inside = ' + str(inside)
"Inside = ['thing', 'other thing', 'sword', 'lamp']"
>>> 'Inside = ' + ', '.join(inside)
'Inside = thing, other thing, another thing'

If you have a list of things that aren't strings and want to add them to the string, you have to decide on the appropriate string representation for those things (unless you're happy with repr):

>>> class Item(object):
...   def __init__(self, desc):
...     self.desc = desc
...   def __repr__(self):
...     return 'Item(' + repr(self.desc) + ')'
...   def __repr__(self):
...     return self.desc
...
>>> inside = [Item('thing'), Item('other thing')]
>>> 'Inside = ' + repr(inside)
... "Inside = [Item('thing'), Item('other thing')]"
>>> 'Inside = ' + str(inside)
... "Inside = [Item('thing'), Item('other thing')]"
>>> 'Inside = ' + ', '.join(str(i) for i in inside)
... 'Inside = thing, other thing'

Notice that just calling str on a list of Items calls repr on the individual items; if you want to call str on them, you have to do it explicitly; that's what the str(i) for i in inside part is for.

Putting it all together:

class Backpack:
    def __init__(self):
        self.inside = []
    def add(self, toadd):
        self.inside.append(toadd)
    def addmany(self, listtoadd):
        self.inside += listtoadd
    def __str__(self):
        return ', '.join(str(i) for i in self.inside)

pack = Backpack()
pack.add('thing')
pack.add('other thing')
pack.add('another thing')
print 'Your backpack contains:', pack

When you run this, it will print:

Your backpack contains: thing, other thing, another thing
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • I'm really trying to add a list of `Item`s to a string, so that might comlpicate things – SuperCheezGi Nov 02 '12 at 22:58
  • You need to define what it means to turn an `Item`, or a list of `Items`, into a string. Once you do that, adding it to a string is easy. I'll edit my answer to give more details. – abarnert Nov 02 '12 at 23:02
  • Ha, +1 because I just realized that my edit overlapped with what you mentioned in your first section :) Sorry for the repeat. – RocketDonkey Nov 02 '12 at 23:06
  • @SuperCheezGi Per your comment above, this is the answer you want :) – RocketDonkey Nov 02 '12 at 23:09
5

You could try this:

In [4]: s = 'Your backpack contains '

In [5]: l = ['item1', 'item2', 'item3']

In [6]: print s + ', '.join(l)
Your backpack contains item1, item2, item3

The join method is a bit odd compared to other Python methods in its setup, but in this case it means 'Take this list and convert it to a string, joining the elements together with a comma and a space'. It is a bit odd because you specify the string with which to join first, which is a little outside of the ordinary but becomes second nature soon :) See here for a discussion.

If you are looking to add items to inside (a list), the primary way to add items to a list is to use the append method. You then use join to bring all the items together as a string:

In [11]: inside = []

In [12]: inside.append('item1')

In [13]: inside.append('item2')

In [14]: inside.append('item3')

In [15]: print 'Your backpack contains ' + ', '.join(inside)
Your backpack contains item1, item2, item3
Community
  • 1
  • 1
RocketDonkey
  • 36,383
  • 7
  • 80
  • 84
  • Good idea, but I would really like a way to expand it easily without having to do all that, but thanks for the idea! – SuperCheezGi Nov 02 '12 at 22:57
  • @SuperCheezGi Hmm, what do you mean exactly? You can actually just replace `l` with `inside` in your example and it would do the same. Were you looking for something different? – RocketDonkey Nov 02 '12 at 22:59
  • I was looking for a way to add things to `inside`, and then have it print all the things inside `inside` – SuperCheezGi Nov 02 '12 at 23:00
  • @SuperCheezGi Oh, so how to actually append things to the `inside` list? – RocketDonkey Nov 02 '12 at 23:01
  • 1
    @SuperCheezGi Also, you were on the right track using a list - that is a better container than a string for this type of information. Using `join` lets you print it out when you're ready to. – RocketDonkey Nov 02 '12 at 23:04
  • Yeah, like adding objects of classes to a list, and then I want to print that all out – SuperCheezGi Nov 02 '12 at 23:07
  • @SuperCheezGi Ah gotcha, `Item` objects. abarnert's answer is the one you want then :) – RocketDonkey Nov 02 '12 at 23:09
  • Actually, I think he wants both answers, since mine just refers to yours for an explanation of `join` instead of actually explaining it… – abarnert Nov 02 '12 at 23:14
  • @abarnert Ha, Inception... I vote yours though - I'd imagine the `__repr__` / `__str__` part was what was causing the confusion. Mine was the easy stuff :) – RocketDonkey Nov 02 '12 at 23:15
  • Personally, I think the fact that `list.__str__` still calls `repr` on its elements is one of the biggest warts that was left unfixed by Python 3.x, because everyone is confused by it, and new users can't even figure out that that's what's confusing them. – abarnert Nov 02 '12 at 23:26
  • @abarnert Agreed - anytime I need to use one or the other I always need a refresher on the relationship. – RocketDonkey Nov 02 '12 at 23:29