Python 2.7 заменяет строку raw_input значением из словаря

Я новичок в программировании (6 недель, самоучка в сети с "codecademy" и "python the hard way"). Я решил, что пришло время начать экспериментировать с написанием кода без направления, и я уперся в стену со своим вторым проектом.

Я пытаюсь создать «секретный кодер», который берет строку raw_input и заменяет все буквы в ней следующей в алфавите. С моими очень ограниченными знаниями я решил, что словарь должен быть подходящим способом. С «небольшой» помощью в гугле я написал следующее:

alpha = {"a" : "b", "b" : "c", "c" : "d", "d" : "e", "e" : "f",  "f" : "g","g" : "h"
         , "h" : "i", "i" : "j", "j" : "k", "k" : "l", "l" : "m","m" : "n", "n" : "o"
         , "o" : "p", "p" : "q", "q" : "r", "r" : "s","s" : "t", "t" : "u", "u" : "v"
         , "v" : "w", "w" : "x", "x" : "y", "y" : "z", "z" : "a"}

entry = raw_input("Please write a sentence you want to encode: ")

def encode(entry, letters):
    for k, v in letters.iteritems():
        if k in alpha:
            entry = entry.replace(k, v)
    return entry
print encode(entry, alpha)

У меня проблема в том, что только половина букв в моей строке заменяется правильными значениями из словаря. «a» и «b» будут напечатаны как «c», тогда как «a» должно быть напечатано как «b», а «b» должно быть напечатано как «c» и так далее.

иллюстрация

Где я полностью теряюсь, так это в том, что когда я заменил каждое значение в своем словаре числами, это сработало отлично.

иллюстрация bis

В этом суть, я действительно не понимаю, что не так с моим кодом.

Спасибо заранее за вашу помощь.

PS: Это был мой самый первый пост на stackoverflow, надеюсь, я сделал все как надо.

РЕДАКТИРОВАТЬ: Поскольку я пока не могу дать репутацию, я просто поблагодарю вас всех за ваши полезные ответы. Теперь я вижу немного яснее, где моя ошибка, и я воспользуюсь предоставленной здесь информацией, чтобы исправить свой код и поработать над его правильным пониманием. Также я вижу, что есть гораздо более логичные и простые подходы к решению такого рода проблем. Функции все еще немного размыты для меня, но я думаю, что это нормально так рано.


person Gorian    schedule 19.08.2016    source источник
comment
вам нужно зацикливаться на записи, а не на буквах, и присоединять каждый символ обратно с помощью ''   -  person YOU    schedule 19.08.2016
comment
Представьте себе этот сценарий... у вас есть a в вашей строке, и вы зацикливаете и меняете все a на b, но затем вы выполняете цикл и меняете все b на c (которые могут включать a, которые вы изменили на bs и т.д...)   -  person Jon Clements♦    schedule 19.08.2016
comment
:D Чувак, мне нравится твой энтузиазм. Python удобен, но мощен, поэтому аналогичным упражнением будет шифрование ваших сообщений с использованием реальных криптографических решений — убедитесь сами, насколько просто это делается с Python stackoverflow.com/questions/30056762/ :)   -  person Miro Rodozov    schedule 19.08.2016
comment
Как говорили многие другие, вы можете просто повторить, как в for e in entry: result += letters[e]..., и python сделает остальную работу за вас. Что-то, что вам стоит усвоить (чем раньше, тем лучше), это то, что вы не должны изменять объект, над которым вы работаете, это избавит вас от множества головных болей в будущем.   -  person    schedule 19.08.2016


Ответы (5)


Xetnus прав, вам нужно перебирать переменную ввода вместо букв. может быть что-то вроде этого

def encode(entry, letters):
    new_entry = ''
    for letter in entry:
        if letter in letters:
            new_entry += letters[letter]
    return new_entry
print encode(entry, alpha)
person davidejones    schedule 19.08.2016

Проблема в том, что, поскольку вы перебираете словарь вместо строки, вы можете много раз заменять исходный символ. Например, при заданном вводе 'ab' первая замена приведет к 'bb', а вторая к 'cc' в случае, если iteritems возвращает ключи в порядке a, b. Обратите внимание, что поскольку словарь представляет собой неупорядоченную коллекцию, порядок возвращаемых элементов является случайным.

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

def encode(entry, letters):
    return ''.join(letters.get(c, c) for c in entry)

В приведенном выше примере вызывается get вместо использования оператора индекса для обработки случаи, когда alpha не содержит буквы в исходной строке. Разница между get и оператором индекса заключается в том, что get принимает второй аргумент, который является значением по умолчанию, которое будет возвращено в случае, если этот ключ не существует. В приведенном выше примере значением по умолчанию является сам символ.

person niemmi    schedule 19.08.2016
comment
Довольно чистое решение (я проголосовал за него), поскольку ОП — новичок, было бы здорово дать более широкое объяснение. Например, метод get() и то, как он выбирает значение из букв или использует предоставленный ключ по умолчанию, если элемент не найден. - person ; 19.08.2016

Словари не упорядочены, поэтому вы заменяете некоторые буквы ('a' -> 'b'), а другие пропускаете.

Для вашего назидания то, что вы делаете, называется rot (вращение). Самый известный из них — rot13.

Самостоятельное написание полезно, когда вы только начинаете, но есть классная стандартная библиотечная функция под названием string.maketrans, которая сделает именно это!

person dreamriver    schedule 19.08.2016

Другие указали, как это сделать правильно, используя словарь в качестве поиска. Однако вы также можете использовать метод str.translate, который позволяет избежать поиска и перестроения строки.

import string

trans = string.maketrans(
    'abcdefghijklmnopqrstuvwxyz', # from...
    'bcdefghijklmnopqrstuvwxyza' # to
)

print raw_input('Please enter something to encode: ').translate(trans)
person Jon Clements♦    schedule 19.08.2016
comment
Это очень элегантный и простой способ сделать то, что я хотел сделать, и я обязательно буду использовать его, так как уже вижу, как я могу заставить свой код выполнять более сложные манипуляции со строками. Я буду работать над тем, чтобы моя функция делала то, что я хотел, с помощью других ответов, а затем, как только я смогу правильно ее закодировать, я переключусь на использование метода str.translate из-за его простоты. Спасибо, что предложили это. - person Gorian; 19.08.2016

def encode(entry, letters):
    for k, v in letters.iteritems():
        if k in alpha:
            entry = entry.replace(k, v)
    return entry
print encode(entry, alpha)

Вызывая encode(entry, alpha) в своей функции печати, вы передаете функции encode() словарь alpha в качестве переменной letters в функции. Затем вы используете итератор для перебора переменной letters (которая является словарем alpha). Затем ваш оператор if проверяет, находится ли это k (которое вы только что получили из переменной letters, которая является словарем alpha) в словаре alpha, что, конечно, так и есть.

Вместо этого вам нужно будет сделать что-то вроде этого:

for k, v in letters.iteritems():
    if k in entry:
        entry = entry.replace(k, v)
person Xetnus    schedule 19.08.2016