Я хочу создать программу, которая подсчитывает «значение» слова, добавляя значения, заданные его буквам, на основе их первой позиции в слове (в качестве упражнения я новичок в Python).
То есть . "foo" вернул бы 5 (как 'f' = 1, 'o' = 2), а "bar" вернул бы 6 (как 'b' = 1, 'a' = 2, 'r' = 3 ) .

Вот мой код:

# -*- coding: utf-8 -*-
 def ppn(word):
    word = list(word)
    cipher = dict()
    i = 1
    e = 0

    for letter in word:
        if letter not in cipher:
            cipher[letter] = i
            e += i
            i += 1
        else:
            e += cipher[letter]
    return ''.join(word) + ": " + str(e)


if __name__ == "__main__":
    print ppn(str(raw_input()))

Он работает хорошо, однако для слов, содержащих такие символы, как «ł», «ą» и т. Д., Он не возвращает правильное значение (я думаю, это потому, что он сначала переводит эти буквы в коды Unicode). Есть ли способ обойти это и заставить интерпретатора воспринимать все буквы как отдельные буквы?

1
Cube. 17 Дек 2015 в 20:36

3 ответа

Лучший ответ

Декодируйте входные данные в Unicode, затем везде используйте Unicode, а затем декодируйте при выводе.

Конкретно вам нужно будет изменить

print ppn(str(raw_input()))

Чтобы

print ppn(raw_input().decode(sys.stdin.encoding))

Это расшифрует ваш ввод. Тогда вам также нужно будет изменить

''.join(word) + ": " + str(e)

Чтобы

u''.join(word) + u': ' + unicode(e)

Это заставляет весь ваш код использовать объекты Юникода внутри.

Print будет правильно кодировать юникод в соответствии с любой кодировкой, используемой вашим терминалом, но вы также можете указать ее, если вам нужно.

В качестве альтернативы вы можете сделать именно то, что у вас уже есть, но запустить его с Python 3.

Для получения дополнительной информации, пожалуйста, прочитайте этот очень полезный доклад на эту тему

2
Chad S. 17 Дек 2015 в 17:53

Все ответы до сих пор объяснили, что делать, но не то, что происходит, поэтому вот некоторые подсказки.

Когда вы используете raw_input() с Python 2, вам возвращается строка байтов (input() на Python 3 ведет себя по-другому). Большинство символов Юникода не могут быть представлены в виде одного байта, потому что символов Юникода больше, чем значений, которые могут быть представлены байтом.

Такие символы, как ł или ą, при кодировании с использованием utf-8 или других кодировок, могут занимать два байта или более:

>>> 'ł'
'\xc5\x82'
>>> 'ą'
'\xc4\x85'

Ваша оригинальная программа интерпретирует эти два байта как отдельные символы, что приводит к неверным результатам.

Python предлагает альтернативу байтовой строке: строки Unicode. При использовании строки Unicode один символ отображается точно как один символ (внутреннее представление строки непрозрачно), и возникшая проблема не может возникнуть.

Следовательно, декодирование байтовой строки в строку Unicode - это путь.

2
Andrea Corbellini 17 Дек 2015 в 17:57

Расшифруйте кодировку вашей оболочки:

if __name__ == "__main__":
    import sys
    print ppn((raw_input()).decode(sys.stdin.encoding))

Для системы Unix обычно UTF-8 работает. В Windows все может быть иначе. Для сохранения используйте sys.stdin.encoding. Вы никогда не знаете, где будет выполняться ваш скрипт.

Или даже лучше. переключиться на Python 3:

# -*- coding: utf-8 -*-

import sys

assert sys.version_info.major > 2


def ppn(word):
    word = list(word)
    cipher = dict()
    i = 1
    e = 0

    for letter in word:
        if letter not in cipher:
            cipher[letter] = i
            e += i
            i += 1
        else:
            e += cipher[letter]
    return ''.join(word) + ": " + str(e)

if __name__ == "__main__":
    print(ppn(str(input())))

В Python 3 строки по умолчанию являются Unicode. Так что нет необходимости в расшифровке бизнеса.

2
Mike Müller 17 Дек 2015 в 17:55