首页 > 解决方案 > 出于某种原因,只要在 if 语句中检查条件,就会重置列表 chars 的值,从而破坏程序

问题描述

我正在尝试制作一个接收字符串并运行以下加密算法的函数:字母表中奇数位置 i 处的每个字符都将使用位置 i + 1 处的字符进行加密,并且偶数位置处的每个字符我将用位置 i - 1 处的字符加密。换句话说,“a”用“b”加密,“b”用“a”加密,“c”用“d”加密,“d”用“c”加密,以及很快。小写字符应保持小写,大写字符应保持大写。换句话说,“bob”将输出为“apa”。

尽管我最终发现了这个问题,但我仍然不知道为什么在我的条件句中使用 chars[i] 而不是 stg[i] 会破坏程序。从我的观察来看,该列表似乎是随机重置的。谁能解释为什么交换变量修复了我的程序?谢谢!

损坏的程序:

def easyCryto(stg=''):

    # Alphabet list
    alpha = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    cap_alpha = [i.upper() for i in alpha]
    
    # Converts the string into a list
    chars = []
    for char in stg:
        chars.append(char)

    # Encyription Algorithm
    for i in range(len(chars)):
        for j in range(len(alpha)):
            
            # Checks if letter are odd
            if (j + 1) % 2 == 1:
                if chars[i] == alpha[j]:
                    try: # Block 1
                        if chars[i] not in cap_alpha:
                            chars[i] = alpha[j + 1]
                        else:
                            chars[i] = cap_alpha[j + 1]
                    except:
                        if chars[i] not in cap_alpha:
                            chars[i] = alpha[0]
                        else:
                            chars[i] = cap_alpha[0]

                elif chars[i] == cap_alpha[j]:
                    chars[i] = cap_alpha[j + 1]

            # Checks if letter are even
            elif (j + 1) % 2 == 0:
                if chars[i] == alpha[j]:
                    try: # Block 1
                        if chars[i] not in cap_alpha:
                            chars[i] = alpha[j - 1]
                        else:
                            chars[i] = cap_alpha[j - 1]

                    except:
                        if chars[i] not in cap_alpha:
                            chars[i] = alpha[-1]
                        else:
                            chars[i] = cap_alpha[-1]

                elif chars[i] == cap_alpha[j]:
                    chars[i] = cap_alpha[j - 1]

    return ''.join(chars)

print(easyCryto('Willy'))

固定程序:

def easyCryto(stg=''):

    # Alphabet list
    alpha = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    cap_alpha = [i.upper() for i in alpha]
    
    # Converts the string into a list
    chars = []
    for char in stg:
        chars.append(char)

    # Encyription Algorithm
    for i in range(len(chars)):
        for j in range(len(alpha)):

            # Checks if letter are odd
            if (j + 1) % 2 == 1:
                if stg[i] == alpha[j]:
                    try: # Block 1
                        if stg[i] not in cap_alpha:
                            chars[i] = alpha[j + 1]
                        else:
                            chars[i] = cap_alpha[j + 1]
                    except:
                        if stg[i] not in cap_alpha:
                            chars[i] = alpha[0]
                        else:
                            chars[i] = cap_alpha[0]

                elif stg[i] == cap_alpha[j]:
                    chars[i] = cap_alpha[j + 1]

            # Checks if letter are even
            elif (j + 1) % 2 == 0:
                if stg[i] == alpha[j]:
                    try: # Block 1
                        if stg[i] not in cap_alpha:
                            chars[i] = alpha[j - 1]
                        else:
                            chars[i] = cap_alpha[j - 1]

                    except:
                        if stg[i] not in cap_alpha:
                            chars[i] = alpha[-1]
                        else:
                            chars[i] = cap_alpha[-1]

                elif stg[i] == cap_alpha[j]:
                    chars[i] = cap_alpha[j - 1]

    return ''.join(chars)

print(easyCryto('bob'))

标签: pythonstringlistalgorithm

解决方案


问题是您在更换后永远不会跳出循环,因此更换循环会继续进行这在替换“向后”时不是问题,例如用 a 替换 b,因为您正在alpha向前迭代,所以它不会再次匹配。但是,当您替换a为时b,在循环的下一次迭代中,它将立即找到一个新的替换匹配项并b(最初a)交换回a.

只需打印替换循环的状态即可轻松查看:

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

c = chars[i], a = alpha[j]. 在c=b您可以看到替换很快完成,然后我们无缘无故地继续进行,但是在 上c=o,您可以看到它到达a=o,翻转到c=p但在那个点a=p所以我们翻转回c=o

通过使用stg来检查这不是一个因素,因为原始数据没有被翻转。另一种方法是break在您找到alpha[j]匹配的 a之后chars[i]

该脚本似乎过于复杂:

  • 您正在检查中cap_alpha 进行检查alpha,因为这些集合是不重叠的,我看不出它怎么能做一些有用的事情。
  • try/except 似乎没有用?我本可以看到一个模数问题,但是在你的方案z中被交换了y所以没有任何有趣的事情发生

更重要的是,您没有使用 Python 的工具,例如string已经提供了字母表,str.translate可以采用转换表,list.index将返回列表中项目的索引(但是当它没有找到任何东西时会引发异常,这str.find很方便,因为它然后返回None),chr并将ord从代码点数字转换为代码点数字,您可以使用位操作来翻转数字,...

您可能可以使用位旋转来做到这一点(它甚至可能很有趣),但作为第一个近似值,我只是构建一个翻译表并使用str.translate。这不是最容易掌握的东西,但一旦你掌握它就很方便:

# str.maketrans can take various formats to build the translation
# table. Here we're going to use the simplest, a dictionary mapping
# unicode ordinals (letter codes) to other unicode ordinals, the
# mapping is the transformation we want to define
tr = {}
# iterate on the codes of "odd" letters (a, c, e, g, ...) and create
# the entries to map both forward (a -> b) and backwards (b -> a)
for letter in range(ord('a'), ord('z'), 2):
    tr[letter] = letter+1
    tr[letter+1] = letter
# repeat for uppercase
for letter in range(ord('A'), ord('Z'), 2):
    tr[letter] = letter+1
    tr[letter+1] = letter
table = str.maketrans(tr)

def easyCryto(stg=''):
    return stg.translate(table)

print(easyCryto('Willy'))

推荐阅读