String concatenation

  • Thread starter Leif B. Kristensen
  • Start date
L

Leif B. Kristensen

Having recently started with Python, I've written this little function
to retrieve place parts from a database and concatenate them to a
string. While it certainly works, and is also considerably shorter than
the PHP code that I originally wrote, I'm pretty convinced that there
should be an even better way to do it. Can anybody show me how to write
the string concatenation part in a more Pythonesque syntax?

def get_place(x):
c=db.cursor()
c.execute("select place_lvl1, place_lvl2, \
place_lvl3, place_lvl4, place_lvl5 \
from place where place_id = %d" % (x))
res=c.fetchone()
place = ''
for i in range(5):
tmp = res
if tmp[:1] != '-' and len(tmp) != 0:
place = place + ', ' + (res)
return place[2:]

regards,
 
P

Paul Rubin

Leif B. Kristensen said:
Having recently started with Python, I've written this little function
to retrieve place parts from a database and concatenate them to a
string. While it certainly works, and is also considerably shorter than
the PHP code that I originally wrote, I'm pretty convinced that there
should be an even better way to do it. Can anybody show me how to write
the string concatenation part in a more Pythonesque syntax?
...
for i in range(5):
tmp = res
if tmp[:1] != '-' and len(tmp) != 0:
place = place + ', ' + (res)
return place[2:]


Not tested:

tmp = [x for x in res if x and x[0] != '-']
return ', '.join(tmp)

Explanation:

1) you can use "for x in res" instead of looping through range(5),
since you know that res has 5 elements (from the sql result).

2) x[:1] is the same as x[0] as long as x has at least 1 char (otherwise
it throws an exception)

3) To prevent the exception, test for x being nonempty BEFORE examining x[0]

4) sep.join(stringlist) is the standard way to join a bunch of strings
together, separated by sep.
 
L

Leif B. Kristensen

Paul said:
Not tested:

tmp = [x for x in res if x and x[0] != '-']
return ', '.join(tmp)

Paul,
that looks a lot more like the examples in "Dive Into Python" which I'm
reading at the moment. But the snake won't swallow:

tmp = [x for x in res if x and x[0] != '-']
^
SyntaxError: invalid syntax

I wonder what it's really trying to tell me?

regards,
 
E

Erik Max Francis

Leif B. Kristensen said:
that looks a lot more like the examples in "Dive Into Python" which
I'm
reading at the moment. But the snake won't swallow:

tmp = [x for x in res if x and x[0] != '-']
^
SyntaxError: invalid syntax

I wonder what it's really trying to tell me?

Probably you included the initial spaces, which is a no-no:
File "<stdin>", line 1
b = 2
^
SyntaxError: invalid syntax
 
L

Leif B. Kristensen

Erik said:
Probably you included the initial spaces, which is a no-no:

No I didn't. The text is properly aligned. The relevant code now looks
exactly like this:

res=c.fetchone()
tmp=[x for x in res if x and x[0] != '-']
return ', '.join(tmp)

And here's what the interpreter says:

tmp=[x for x in res if x and x[0] != '-']
^
SyntaxError: invalid syntax

The marker has moved to the right, maybe because I removed the spaces on
both sides of the = sign?

regards,
 
E

Erik Max Francis

Leif B. Kristensen said:
And here's what the interpreter says:

tmp=[x for x in res if x and x[0] != '-']
^
SyntaxError: invalid syntax

The marker has moved to the right, maybe because I removed the spaces
on
both sides of the = sign?

At this point I don't know what's going on since there's a communication
problem; Python's exception specification is based on the code you
entered, not the code it thought you meant, so you're having a
cutting-and-pasting problem at least on one side here.

If indentation is not to blame, it's possible that the problem is that
you're not running a version of Python that understands list
comprehensions.
 
L

Leif B. Kristensen

Erik said:
At this point I don't know what's going on since there's a
communication problem; Python's exception specification is based on
the code you entered, not the code it thought you meant, so you're
having a cutting-and-pasting problem at least on one side here.

Erik,
After entering Paul's two lines by hand, it suddenly works. You must be
right about the cutting-and-pasting problem, though I don't understand
why lifting text from KNode to KWrite shouldn't work.
If indentation is not to blame, it's possible that the problem is that
you're not running a version of Python that understands list
comprehensions.

bash-2.05b$ python
Python 2.3.3 (#1, Jan 24 2004, 10:16:14)
[GCC 3.2.3 20030422 (Gentoo Linux 1.4 3.2.3-r3, propolice)] on linux2
Type "help", "copyright", "credits" or "license" for more information.

regards,
 
E

Erik Max Francis

Leif B. Kristensen said:
After entering Paul's two lines by hand, it suddenly works. You must
be
right about the cutting-and-pasting problem, though I don't understand
why lifting text from KNode to KWrite shouldn't work.

Maybe it's grabbing tabs, or obscure unprintable whitespace you can't
see. Certainly what you're pasting in to these posts is intended,
whether or not you did that manually.
 
L

Leif B. Kristensen

Paul said:
Leif B. Kristensen said:
for i in range(5):
tmp = res
if tmp[:1] != '-' and len(tmp) != 0:
place = place + ', ' + (res)
return place[2:]


tmp = [x for x in res if x and x[0] != '-']
return ', '.join(tmp)


Now I got it working, and it's really neat! It's almost incredible that
you can do all this with just two lines of code.

Thank you very much.

regards,
 
L

Leif B. Kristensen

Erik said:
Maybe it's grabbing tabs, or obscure unprintable whitespace you can't
see. Certainly what you're pasting in to these posts is intended,
whether or not you did that manually.

It may be a bug in KWrite. As I entered it manually, I noticed that the
pasted text wasn't syntax highlighted.

Yeah, I know -- I should use a real editor, like vi or emacs ;-)

regards,
 
L

Leif B. Kristensen

Erik said:
Maybe it's grabbing tabs, or obscure unprintable whitespace you can't
see. Certainly what you're pasting in to these posts is intended,
whether or not you did that manually.

The problem is recognised and confirmed. I posted a description of the
situation on comp.windows.x.kde, and received essentially this answer:

"you will notice that the "space" is an ASCII space (20 hex) in the
working version and ASCII space + 128 (A0 hex) in the non-working
version. Just because the display looks the same does not mean it is
the same."

regards,
 
P

Peter Otten

Leif said:
The "feature" is also submitted to the KDE bugtrack, see
<url:http://bugs.kde.org/show_bug.cgi?id=60971>.

Apparently, "real programmers" don't cut and paste code samples from
KNode. Go figure.

I doubt that KNode is to blame. The problem you encountered occured
to me only sporadically. Therefore I guess that the culprit is elsewhere in
the toolchain.

In the meantime, whenever an apparent whitespace generates a syntax error:

<clean160.py>
#!/usr/bin/env python
import string, sys, os

transTable = string.maketrans(chr(160), " ")

if __name__ == "__main__":
for filename in sys.argv[1:]:
s = file(filename).read()
if chr(160) in s:
print "cleaning", filename
os.rename(filename, filename + ".160")
file(filename, "w").write(s.translate(transTable))
else:
print "skipping", filename
<clean160.py>

Peter

PS: I'm not sure if the above reaches you without those vicious blanks, but
I'm confident :)
 
L

Leif B. Kristensen

Paul said:
tmp = [x for x in res if x and x[0] != '-']
return ', '.join(tmp)

Substituting tmp with the real thing, it turns into a one-liner:

return ', '.join([x for x in res if x and x[0] != '-'])

Awesome :)
 
P

Paul Rubin

Leif B. Kristensen said:
tmp = [x for x in res if x and x[0] != '-']
return ', '.join(tmp)

Substituting tmp with the real thing, it turns into a one-liner:

return ', '.join([x for x in res if x and x[0] != '-'])

Awesome :)

Yeah, I wrote it that way at first, but figured it was obscure enough
already if you weren't used to list comprehensions, so I put back the
tmp variable.
 
L

Leif B. Kristensen

Peter said:
In the meantime, whenever an apparent whitespace generates a syntax
error:

<clean160.py>
PS: I'm not sure if the above reaches you without those vicious
blanks, but I'm confident :)

Thanks, Peter.

It was of course full of \xa0's. But now that I know about the bug, a
search/replace takes only seconds.
 
P

Peter Otten

Leif said:
It was of course full of \xa0's. But now that I know about the bug, a
search/replace takes only seconds.

I copied it back from the newsgroup with no problems, using only KNode and
Kate. This is really strange.

Peter
 
D

Dave Benjamin

Leif B. Kristensen said:
tmp = [x for x in res if x and x[0] != '-']
return ', '.join(tmp)

Substituting tmp with the real thing, it turns into a one-liner:

return ', '.join([x for x in res if x and x[0] != '-'])

Awesome :)

Yeah, I wrote it that way at first, but figured it was obscure enough
already if you weren't used to list comprehensions, so I put back the
tmp variable.

FWIW, I'm used to seeing (and writing) stuff like this, and I don't think
the "tmp" adds any clarity. You could wrap around it with a function,
though, if you needed it often enough:

def join_if(pred, seq, sep):
return sep.join([x for x in seq if pred(x)])

def valid(x):
return x and x[0] != '-'

return join_if(valid, res, ', ')
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top