I've got a list in a Python program that contains a series of numbers, which are themselves ASCII values. How do I convert this into a "regular" string that I can echo to the screen?
Asked
Active
Viewed 2.1e+01k times
9 Answers
164
You are probably looking for 'chr()':
>>> L = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100]
>>> ''.join(chr(i) for i in L)
'hello, world'

Thomas Wouters
- 130,178
- 23
- 148
- 122
-
13I'll bet you created that list L using `[ord(x) for x in 'hello, world']` – zapstar Aug 14 '17 at 06:59
-
1`chars = [chr(i) for i in range(97, 97 + 26)]` – FindOutIslamNow Sep 12 '18 at 10:53
28
Same basic solution as others, but I personally prefer to use map instead of the list comprehension:
>>> L = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100]
>>> ''.join(map(chr,L))
'hello, world'
8
l = [83, 84, 65, 67, 75]
s = "".join([chr(c) for c in l])
print s

Thomas Vander Stichele
- 36,043
- 14
- 56
- 60
8
You can use bytes(list).decode()
to do this - and list(string.encode())
to get the values back.

Wai Ha Lee
- 8,598
- 83
- 57
- 92

Timo Herngreen
- 112
- 1
- 9
6
Perhaps not as Pyhtonic a solution, but easier to read for noobs like me:
charlist = [34, 38, 49, 67, 89, 45, 103, 105, 119, 125]
mystring = ""
for char in charlist:
mystring = mystring + chr(char)
print mystring

David White
- 103
- 3
- 7
3
def working_ascii():
"""
G r e e t i n g s !
71, 114, 101, 101, 116, 105, 110, 103, 115, 33
"""
hello = [71, 114, 101, 101, 116, 105, 110, 103, 115, 33]
pmsg = ''.join(chr(i) for i in hello)
print(pmsg)
for i in range(33, 256):
print(" ascii: {0} char: {1}".format(i, chr(i)))
working_ascii()

ptsivakumar
- 437
- 6
- 4
2
I've timed the existing answers. Code to reproduce is below. TLDR is that bytes(seq).decode()
is by far the fastest. Results here:
test_bytes_decode : 12.8046 μs/rep
test_join_map : 62.1697 μs/rep
test_array_library : 63.7088 μs/rep
test_join_list : 112.021 μs/rep
test_join_iterator : 171.331 μs/rep
test_naive_add : 286.632 μs/rep
Setup was CPython 3.8.2 (32-bit), Windows 10, i7-2600 3.4GHz
Interesting observations:
- The "official" fastest answer (as reposted by Toni Ruža) is now out of date for Python 3, but once fixed is still basically tied for second place
- Joining a mapped sequence is almost twice as fast as a list comprehension
- The list comprehension is faster than its non-list counterpart
Code to reproduce is here:
import array, string, timeit, random
from collections import namedtuple
# Thomas Wouters (https://stackoverflow.com/a/180615/13528444)
def test_join_iterator(seq):
return ''.join(chr(c) for c in seq)
# community wiki (https://stackoverflow.com/a/181057/13528444)
def test_join_map(seq):
return ''.join(map(chr, seq))
# Thomas Vander Stichele (https://stackoverflow.com/a/180617/13528444)
def test_join_list(seq):
return ''.join([chr(c) for c in seq])
# Toni Ruža (https://stackoverflow.com/a/184708/13528444)
# Also from https://www.python.org/doc/essays/list2str/
def test_array_library(seq):
return array.array('b', seq).tobytes().decode() # Updated from tostring() for Python 3
# David White (https://stackoverflow.com/a/34246694/13528444)
def test_naive_add(seq):
output = ''
for c in seq:
output += chr(c)
return output
# Timo Herngreen (https://stackoverflow.com/a/55509509/13528444)
def test_bytes_decode(seq):
return bytes(seq).decode()
RESULT = ''.join(random.choices(string.printable, None, k=1000))
INT_SEQ = [ord(c) for c in RESULT]
REPS=10000
if __name__ == '__main__':
tests = {
name: test
for (name, test) in globals().items()
if name.startswith('test_')
}
Result = namedtuple('Result', ['name', 'passed', 'time', 'reps'])
results = [
Result(
name=name,
passed=test(INT_SEQ) == RESULT,
time=timeit.Timer(
stmt=f'{name}(INT_SEQ)',
setup=f'from __main__ import INT_SEQ, {name}'
).timeit(REPS) / REPS,
reps=REPS)
for name, test in tests.items()
]
results.sort(key=lambda r: r.time if r.passed else float('inf'))
def seconds_per_rep(secs):
(unit, amount) = (
('s', secs) if secs > 1
else ('ms', secs * 10 ** 3) if secs > (10 ** -3)
else ('μs', secs * 10 ** 6) if secs > (10 ** -6)
else ('ns', secs * 10 ** 9))
return f'{amount:.6} {unit}/rep'
max_name_length = max(len(name) for name in tests)
for r in results:
print(
r.name.rjust(max_name_length),
':',
'failed' if not r.passed else seconds_per_rep(r.time))

user13528444
- 31
- 2
-
Also include the python implementation you are using since that can affect the benchmark numbers. Here is how you can retrieve that information https://stackoverflow.com/a/14718168/12160191. – Empty Space May 14 '20 at 07:04
-
@MutableSideEffect Done. I know offhand that it’s CPython, but I had no idea you could find that programmatically – user13528444 May 15 '20 at 18:20
-
0
Question = [67, 121, 98, 101, 114, 71, 105, 114, 108, 122]
print(''.join(chr(number) for number in Question))
-
2Please note that on Stack Overflow it is customary to include some explanation of why the proposed approach answers the question - especially when the question is older and already has an accepted answer. In what way does this suggestion differ and why would it be used instead of an existing answer? – Cindy Meister Dec 09 '18 at 12:20