<p>我能想到的最好的答案是“为什么不呢?”密码不能包含重复项,但代码中没有强制执行该项。相反,您的程序只是生成由字符集组成的具有特定长度的所有字符串。你知道吗</p>
<p>@SimonN说你的输出应该以一个10'a的字符串开始,这是正确的,确实如此。当写入文件时,第一个字符串确实是“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa。你知道吗</p>
<p>@alex067的建议也不能解决这个问题,因为它不仅会导致重复的字符,而且会删除列表中位于它前面的所有字符。最后一点意味着对于长度为3的密码,例如,完全有效的字符串<code>acb</code>、<code>bac</code>等被省略。当然,我们可以用<code>prefix[i+1:]</code>来代替<code>prefix[i:]</code>,但这只解决了前者的问题,而不是后者的问题。你知道吗</p>
<hr/>
<p>如您所知,<code>itertools</code>提供了可能是最好的解决方案,我将在下面介绍这一点。然而,在此之前,我发现一个递归方法非常好:</p>
<pre class="lang-py prettyprint-override"><code>def pwd_rec(curr_charset: str, curr_pwd: str, pwd_len: int) -> List[str]:
result_strs = []
for idx, curr_char in enumerate(curr_charset):
new_pwd = curr_pwd + curr_char
if len(new_pwd) == pwd_len:
result_strs.append(new_pwd)
else:
result_strs.extend(pwd_rec(curr_charset[:idx] + curr_charset[idx+1:], new_pwd, pwd_len))
return result_strs
</code></pre>
<p>下面是该方法的延迟版本,使用生成器而不是列表:</p>
<pre class="lang-py prettyprint-override"><code>def pwd_rec(curr_charset: str, curr_pwd: str, pwd_len: int) -> Iterator[str]:
for idx, curr_char in enumerate(curr_charset):
new_pwd = curr_pwd + curr_char
if len(new_pwd) == pwd_len:
yield new_pwd
else:
yield from pwd_rec(curr_charset[:idx] + curr_charset[idx+1:], new_pwd, pwd_len)
</code></pre>
<hr/>
<p>正如所承诺的,这里有一个使用<code>itertools</code>的方法:</p>
<pre class="lang-py prettyprint-override"><code>import itertools as itt
def pwd_perms(charset: str, pwd_len: int) -> Iterator[str]:
for curr in itt.permutations(charset, pwd_len):
yield ''.join(curr)
</code></pre>
<hr/>
<p>如果您有任何问题,请告诉我:)</p>