Как преобразовать список значений ascii в строку в Python?

У меня есть список в программе Python, содержащий ряд чисел, которые сами по себе являются значениями ASCII. Как преобразовать это в «обычную» строку, которую я могу выводить на экран?


person Electrons_Ahoy    schedule 07.10.2008    source источник


Ответы (7)


Вероятно, вы ищете 'chr ()':

>>> L = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100]
>>> ''.join(chr(i) for i in L)
'hello, world'
person Thomas Wouters    schedule 07.10.2008
comment
Готов поспорить, вы создали этот список L, используя [ord(x) for x in 'hello, world'] - person zapstar; 14.08.2017

Такое же базовое решение, как и у других, но я лично предпочитаю использовать карту вместо понимания списка:


>>> L = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100]
>>> ''.join(map(chr,L))
'hello, world'
person Community    schedule 08.10.2008

import array
def f7(list):
    return array.array('B', list).tostring()

из Шаблоны Python - анекдот оптимизации

person Toni Ruža    schedule 08.10.2008

Возможно, не как решение Pyhtonic, но для таких новичков, как я, его легче читать:

charlist = [34, 38, 49, 67, 89, 45, 103, 105, 119, 125]
mystring = ""
for char in charlist:
    mystring = mystring + chr(char)
print mystring
person David White    schedule 13.12.2015

Вы можете использовать bytes(list).decode() для этого - и list(string.encode()), чтобы вернуть значения.

person Timo Herngreen    schedule 04.04.2019

Я рассчитал существующие ответы. Код для воспроизведения приведен ниже. TL; DR: bytes(seq).decode() - безусловно, самый быстрый. Результаты здесь:

 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

Установка была CPython 3.8.2 (32-разрядная версия), Windows 10, i7-2600 3,4 ГГц

Интересные наблюдения:

  • «Официальный» самый быстрый ответ (как репост Тони Ружа) теперь устарел для Python 3, но после исправления все еще в основном занимает второе место
  • Присоединение к сопоставленной последовательности почти в два раза быстрее, чем понимание списка
  • Понимание списка происходит быстрее, чем его аналог, не являющийся списком

Код для воспроизведения находится здесь:

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))
person user13528444    schedule 14.05.2020
comment
Также включите реализацию Python, которую вы используете, поскольку это может повлиять на результаты тестов. Вот как вы можете получить эту информацию stackoverflow.com/a/14718168/12160191. - person Mutable Side Effect; 14.05.2020
comment
@MutableSideEffect Готово. Я знаю, что это CPython, но понятия не имел, что это можно найти программно. - person user13528444; 15.05.2020

person    schedule
comment
Обратите внимание, что в Stack Overflow принято включать некоторые объяснения того, почему предлагаемый подход отвечает на вопрос, особенно если вопрос более старый и уже имеет принятый ответ. Чем отличается это предложение и почему его следует использовать вместо существующего ответа? - person Cindy Meister; 09.12.2018