Python中的Caesar Cipher函数

15 python caesar-cipher

我正在尝试在Python中创建一个简单的Caesar Cipher函数,它根据用户的输入移动字母,并在最后创建一个最终的新字符串.唯一的问题是最终的密文只显示最后一个移位的字符,而不是一个包含所有移位字符的整个字符串.

这是我的代码:

plainText = raw_input("What is your plaintext? ")
shift = int(raw_input("What is your shift? "))

def caesar(plainText, shift): 

    for ch in plainText:
        if ch.isalpha():
            stayInAlphabet = ord(ch) + shift 
            if stayInAlphabet > ord('z'):
                stayInAlphabet -= 26
            finalLetter = chr(stayInAlphabet)
        cipherText = ""
        cipherText += finalLetter

    print "Your ciphertext is: ", cipherText

    return cipherText

caesar(plainText, shift)
Run Code Online (Sandbox Code Playgroud)

ami*_*des 42

我意识到这个答案并没有真正回答你的问题,但我认为无论如何它都是有用的.以下是使用字符串方法实现caesar密码的另一种方法:

def caesar(plaintext, shift):
    alphabet = string.ascii_lowercase
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    table = string.maketrans(alphabet, shifted_alphabet)
    return plaintext.translate(table)
Run Code Online (Sandbox Code Playgroud)

实际上,由于字符串方法是在C中实现的,因此我们将看到此版本的性能提升.这就是我认为的"pythonic"方式.

  • 上面的解决方案适用于Python 2,但在Python 3中使用`str.maketrans()`而不是`string.maketrans()`. (8认同)
  • 针对多个字母(小写、大写、数字等)的情况,此代码的改进版本:/sf/answers/3821305421/ (2认同)

I82*_*uch 17

你需要cipherText = ""在for循环开始之前移动.你每次循环都要重置它.

def caesar(plainText, shift): 
  cipherText = ""
  for ch in plainText:
    if ch.isalpha():
      stayInAlphabet = ord(ch) + shift 
      if stayInAlphabet > ord('z'):
        stayInAlphabet -= 26
      finalLetter = chr(stayInAlphabet)
      cipherText += finalLetter
  print "Your ciphertext is: ", cipherText
  return cipherText
Run Code Online (Sandbox Code Playgroud)


Geo*_*rgy 11

这是@amillerrodes 答案中代码的改进版本,它适用于不同的字母表,而不仅仅是小写字母:

\n\n
def caesar(text, step, alphabets):\n\n    def shift(alphabet):\n        return alphabet[step:] + alphabet[:step]\n\n    shifted_alphabets = tuple(map(shift, alphabets))\n    joined_aphabets = \'\'.join(alphabets)\n    joined_shifted_alphabets = \'\'.join(shifted_alphabets)\n    table = str.maketrans(joined_aphabets, joined_shifted_alphabets)\n    return text.translate(table)\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用示例:

\n\n
>>> import string\n>>> alphabets = (string.ascii_lowercase, string.ascii_uppercase, string.digits)\n>>> caesar(\'Abc-xyZ.012:789?\xd0\xb6\xc3\xb1\xc3\xa7\', step=4, alphabets=alphabets)\n\'Efg-bcD.456:123?\xd0\xb6\xc3\xb1\xc3\xa7\'\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

参考文献:
\n上的文档str.maketrans
\n上的文档str.translate
\n中的文档string

\n


alv*_*vas 5

使用一些 ASCII 数字技巧:

# See http://ascii.cl/
upper = {ascii:chr(ascii) for ascii in range(65,91)}
lower = {ascii:chr(ascii) for ascii in range(97,123)}
digit = {ascii:chr(ascii) for ascii in range(48,58)}


def ceasar(s, k):
    for c in s:
        o = ord(c)
        # Do not change symbols and digits
        if (o not in upper and o not in lower) or o in digit:
            yield o
        else:
            # If it's in the upper case and
            # that the rotation is within the uppercase
            if o in upper and o + k % 26 in upper:
                yield o + k % 26
            # If it's in the lower case and
            # that the rotation is within the lowercase
            elif o in lower and o + k % 26 in lower:
                yield o + k % 26
            # Otherwise move back 26 spaces after rotation.
            else: # alphabet.
                yield o + k % 26 -26

x = (''.join(map(chr, ceasar(s, k))))
print (x)
Run Code Online (Sandbox Code Playgroud)