计算循环中的迭代总量

时间:2015-01-21 16:36:32

标签: python

我创建了一个生成字符串迭代的程序。但是,我无法打印总数。这是我的代码:     来自itertools导入产品     for commonpasswords中的密码:         password = password.strip('\ n')

基本上我只想要1个数字来突变总数。感谢。

如果你可以帮助我的话,我也会得到一个KeyError'\ r'。

编辑:这是我得到的错误:

Traceback (most recent call last):
  File "test.py", line 17, in <module>
    allPossible = list(product(*([letter] + mapping[letter] for letter in password)))
  File "test.py", line 17, in <genexpr>
    allPossible = list(product(*([letter] + mapping[letter] for letter in password)))
KeyError: '\r'

2 个答案:

答案 0 :(得分:0)

要摆脱KeyError \r,请password.strip('\n')password.strip('\r')

KeyError是什么意思?

这意味着您正试图在mapping词典中查找不存在的值

在这一行

allPossible = list(product(*([letter] + mapping[letter] for letter in password)))

for letter in password逐个浏览这些字母,然后在mapping mapping[letter]中查找可能的替代字。与任何字典一样,如果letter不是mapping中的密钥,则会出现KeyError。

您需要决定如何处理不在字典中的字符。你可以做一些事情

  1. 将该行放在try块中,然后使用except捕获错误。这会从结果中省略该密码,但允许您的代码继续运行
  2. 继续剥离字符(与\n\r一样),直到您确定只在地图中留下字符
  3. 为您可能在字典中找到的所有字符添加映射(例如,将'_':['_']添加为mapping的条目)
  4. 更改您的语句查找突变,以便它只适用于mapping字典中的值。
  5. 在末尾打印一个数字

    修复后,您的代码会输出文件的运行总数突变 - 逐个添加每行的突变

    如果您只想在结尾处打印(即文件总数),请从print(total)行中删除缩进。

    压痕

    您可能误解了python缩进结构 - forwhile后面的每个缩进行将在每个循环中运行一次。您不希望在每个循环上执行print语句,因此请删除缩进。

答案 1 :(得分:0)

  1. 将代码分解为函数可以使理解和重用更容易

  2. 您可以使用dict.get为不在字典中的项目提供默认值;

    v = count.get(ch, 1)
    

    相当于

    try:
        v = count[ch]
    except KeyError:
        v = 1
    
  3. 您可以通过乘以每个字母的替代数量来计算变体的数量;这比实际生成所有可能性并计算它们的速度快

  4. 您可以使用word.strip()代替word.strip("\n").strip("\r");它删除任何前导或尾随制表符或空格字符,但这是无关紧要的,因为它们没有映射,因此不会影响最终总数。

  5. 所以,

    mapping = {
        'a': ['A', '@'],    'b': ['B', '8'],    'c': ['C', '('],
        'd': ['D'],         'e': ['E', '3'],    'f': ['F'],
        'g': ['G'],         'h': ['H'],         'i': ['I', '1'],
        'j': ['J'],         'k': ['K'],         'l': ['L'], 
        'm': ['M'],         'n': ['N'],         'o': ['O', '0'],
        'p': ['P'],         'q': ['Q'],         'r': ['R'], 
        's': ['S'],         't': ['T', '7'],    'u': ['U'], 
        'v': ['V'],         'w': ['W'],         'x': ['X'], 
        'y': ['Y'],         'z': ['Z'],         '1': ['i', 'I'],
        '2': ['2'],         '3': ['e', 'E'],    '4': ['H', 'h'], 
        '5': ['s', 'S'],    '6': ['b'],         '7': ['L', 'l'], 
        '8': ['B'],         '9': ['9'],         '0': ['o', '0']
    }
    
    # precalculate number of variants for each letter
    count = {ch:len(lst)+1 for ch,lst in mapping.items()}
    
    def variants(word):
        """
        Return the number of variations possible
          by replacing some letters in `word` with
          their alternatives from `mapping`
        """
        p = 1
        for ch in word:
            p *= count.get(ch, 1)
        return p
    
    def total_variants(wordlist):
        return sum(variants(word) for word in wordlist)
    
    def main():
        with open("commonpasswords.txt") as inf:
            print(total_variants(line.strip() for line in inf))
    
    if __name__ == "__main__":
        main()