Python3 заменяет ord() и chr()

        for i in word:
            c = ord(i) - int(key)
            if c < 97:
                c = c + 26
            b = chr(c)
            text += b

Есть ли другой способ заменить это без ord() и chr()?

Большое спасибо!


person jack hu    schedule 20.09.2020    source источник
comment
ord() и chr() встроены в python. Есть конкретная причина их замены?   -  person pastaleg    schedule 20.09.2020
comment
Вы можете предварительно вычислить сопоставление (используя dict) от исходных символов к символам назначения и использовать этот dict для замены одного за другим char из слова.   -  person Arty    schedule 20.09.2020
comment
Если есть какая-то особая причина опустить chr/ord, например. какое-то школьное задание, затем вы также можете преобразовать строку в байты, используя bs = word.encode('utf-16'), затем изменить некоторые байты и преобразовать обратно в строку, используя word = bs.decode('utf-16').   -  person Arty    schedule 20.09.2020
comment
И сделайте key целым числом перед циклом   -  person Pynchia    schedule 20.09.2020


Ответы (1)


Вот код, использующий модуль numpy плюс кодировка/декодирование UTF-32. Этот код будет очень быстрым для больших данных и не требует циклов Python.

Модуль numpy легко устанавливается с помощью python -m pip install numpy. Если вам нужно решение без numpy, с использованием простого Python, и скорость работы не является проблемой, скажите мне, и я перепишу, но в простом Python код будет работать намного медленнее на больших данных.

Вы также можете запустить этот код здесь.

# Needs: python -m pip install numpy
import numpy as np

word = 'Duck'
key = 1

a = np.frombuffer(word.encode('utf-32-le'), dtype = np.int32)
a = a - key
a[a < 97] += 26

text = a.tobytes().decode('utf-32-le')

print(text)

И аналогичное более медленное следующее решение, но без numpy, используя только стандартный встроенный модуль Python struct. Вы также можете запустить следующий код онлайн.

import struct

word = 'Duck'
key = 1

text = ''

for i in word:
    c = struct.unpack('<I', i.encode('utf-32-le'))[0] - int(key)
    if c < 97:
        c = c + 26
    b = struct.pack('<I', c).decode('utf-32-le')
    text += b
    
print(text)

Другое решение ниже без использования какого-либо модуля. Выполнить следующий код онлайн.

word = 'Duck'
key = 1

text = ''

for i in word:
    c = int(i.encode('utf-32-be').hex(), 16) - int(key)
    if c < 97:
        c = c + 26
    b = bytes.fromhex(hex(c)[2:].zfill(8)).decode('utf-32-be')
    text += b
    
print(text)

Если текстовые символы взяты только из набора ASCII, код можно упростить еще больше (запустите этот код онлайн):

word = 'Duck'
key = 1

text = ''

for i in word:
    c = i.encode('ascii')[0] - int(key)
    if c < 97:
        c = c + 26
    b = bytes((c,)).decode('ascii')
    text += b
    
print(text)

Еще одно решение для символов ASCII с использованием двух таблиц (запустите этот код онлайн)

word = 'Duck'
key = 1

tmp = [(c, i) for i, c in enumerate(bytes(range(128)).decode('ascii'))]
c2i = dict(tmp)
i2c = [e[0] for e in tmp]

text = ''

for i in word:
    c = c2i[i] - int(key)
    if c < 97:
        c = c + 26
    b = i2c[c]
    text += b
    
print(text)

Предыдущий код можно расширить с ASCII на более широкий набор символов (например, 16-битный), заменив следующую строку (запустите этот код онлайн):

tmp = [(bytes.fromhex(hex(i)[2:].zfill(8)).decode('utf-32-be', 'replace'), i) for i in range(1 << 16)]
person Arty    schedule 20.09.2020
comment
Пожалуйста, разъясните. В чем причина использования struct? - person Pynchia; 20.09.2020
comment
@Pynchia Причина использования структуры связана с просьбой спрашивающего не использовать ord/chr, поэтому encode/decode + struct unpack/pack заменяет ord/chr. - person Arty; 20.09.2020
comment
Может есть более простой способ конвертировать 4 байта в int и обратно, а не struct. - person Arty; 20.09.2020
comment
Я также могу использовать int(bytes_.hex(), 16). - person Arty; 20.09.2020
comment
Добавлено решение без каких-либо модулей. - person Arty; 20.09.2020
comment
В любом случае решение numpy работает быстрее всего и может обрабатывать большие тексты без каких-либо циклов. Также самый короткий по длине код. - person Arty; 20.09.2020
comment
Также код можно упростить, если текст содержит только символы ascii. Я ожидал каких-либо символов в тексте, поэтому использовал кодировку UTF-32. - person Arty; 20.09.2020