python密码规则验证

时间:2015-04-24 20:09:05

标签: python

我正在练习一些Python而且我无法理解为什么这段代码不会占用 - 函数需要一个字符串,如果它的长度至少为10个字符,则至少有1个数字,1个小写字母和1个大写字母信,它应该返回True。此外,还有一种比我对所有这些嵌套条件更简洁的方式来编写它。谢谢大家!

simplify

7 个答案:

答案 0 :(得分:5)

以下内容应该有效,并删除不必要的导入:

def checkio(data):
    return len(data) >= 10 and any(char.isdigit() for char in data) and any(char.islower() for char in data) and any(char.isupper() for char in data)

您可以默认迭代字符串,每个字符串都有您可以使用的isdigit,islower等方法。如果传递给它的iterable返回的任何值为true,any()方法返回True,something(value) for value in iterable语法创建一个生成器表达式,它迭代字符串的每个字符并检查它是否为a数字/小写/大写字符。

基于this answer

基准时间,我可怕的基准代码(但似乎可以完成这项工作):

from time import time
import re

data = "ULFFunH8ni" # the password

def benchmark(method): # benchmark method, loops 1000000 times and prints how much it took
    start = time()
    for _ in range(1000000): method(data)
    print(time() - start)

def checkio_kasra(data): # Kasra's answer
    return len(data) >= 10 and all([any(i.isdigit() for i in data),any(i.islower() for i in data),any(i.isupper() for i in data)])

def checkio_andreysabitov(data): # Andrey Sabitov's regex-based answer
    if len(data) < 10:
        return False

    digital = re.compile('[0-9]+')
    capital = re.compile('[A-Z]+')
    lower = re.compile('[a-z]+')

    return (digital.search(data) is not None) and (capital.search(data) is not None)  and (lower.search(data) is not None)

def checkio_andredaniel(data): # My answer
    return len(data) >= 10 and any(char.isdigit() for char in data) and any(char.islower() for char in data) and any(char.isupper() for char in data)

def checkio_shashank_bitmask(data):
    if len(data) < 10: return False
    lud_bitmask = 0
    for ch in data:
        if ch.islower():
            lud_bitmask |= 4
            if lud_bitmask == 7: return True
        elif ch.isupper():
            lud_bitmask |= 2
            if lud_bitmask == 7: return True
        elif ch.isdigit():
            lud_bitmask |= 1
            if lud_bitmask == 7: return True
    return False

def checkio_shashank_pure_regex(data):
    return bool(re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z]).{10}', data))

def checkio_shashank_impure_regex(data):
    return len(data) >= 10 and re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z])', data)

benchmark(checkio_kasra)
benchmark(checkio_andreysabitov)
benchmark(checkio_andredaniel)
benchmark(checkio_shashank_bitmask)
benchmark(checkio_shashank_pure_regex)
benchmark(checkio_shashank_impure_regex)

结果,在我的运行Windows 7和Python 3.4.x的低端平板电脑上运行(运行两次以确定):

$ python pass.py
6.333611011505127 # Shashank
9.625216960906982 # Kasra
11.450419902801514 # Andrey Sabitov
8.36161494255066 # Me

但是,如果1XYZXYZXYZ的半输入不正确(长度和数字都很好,但都是大写的),某些解决方案无法提前停止:

7.456813097000122 # Shashank
9.328815937042236 # Kasra
11.169620037078857 # Andrey Sabitov
6.349210977554321 # Me

请注意,这些基准测试未考虑最终编辑。我建议你使用最新的答案在自己的机器上运行基准测试。随意用新结果更新这篇文章。

答案 1 :(得分:1)

import re    
def checkio(data):
    if len(data) < 10:
        return False

    digital = re.compile('[0-9]+')
    capital = re.compile('[A-Z]+')
    lower = re.compile('[a-z]+')

    return (digital.search(data) is not None) and (capital.search(data) is not None)  and (lower.search(data) is not None)

答案 2 :(得分:1)

您可以在any中使用all函数的3生成器表达式:

def checkio(data): 
    return len(data) >= 10 and all([any(i.isdigit() for i in data),any(i.islower() for i in data),any(i.isupper() for i in data)])   

演示:

>>> checkio('1&*^&^%%gA')
True
>>> checkio('1&*^&^%%gf')
False

答案 3 :(得分:1)

一种独特的方法是使用bitmask

def checkio_shashank_bitmask(data):
    if len(data) < 10: return False
    lud_bitmask = 0
    for ch in data:
        if ch.islower():
            lud_bitmask |= 4
            if lud_bitmask == 7: return True
        elif ch.isupper():
            lud_bitmask |= 2
            if lud_bitmask == 7: return True
        elif ch.isdigit():
            lud_bitmask |= 1
            if lud_bitmask == 7: return True
    return False

print(checkio('5Hortpass')) # False
print(checkio('dumbpa55w0rd')) # False
print(checkio('DumbPassword')) # False
print(checkio('DumbPassword2015')) # True

这可以很好地适应大型输入和停止。

以下是我认为成为优化的正则表达式解决方案,并且尽快停止非贪婪的积极前瞻:

import re

def checkio_shashank_pure_regex(data):
    return bool(re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z]).{10}', data))

但是,我不是正则表达式专家,所以如果你有任何优化想法,请告诉我。

通过一些进一步的测试,我已经确定这个速度要快一点,并且至少对于正确和错误的输入而言,这可能是迄今为止最快的解决方案,至少使用高度优化的正则表达式模块:

def checkio_shashank_impure_regex(data):
    return len(data) >= 10 and re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z])', data)

答案 4 :(得分:0)

我发现这个功能既有效又美观。

def check(password):
    """Returns True only if password is strong enough."""
    if  (len(password) >= 10
     and any(char.isdigit() for char in password)
     and any(char.islower() for char in password) 
     and any(char.isupper() for char in password)):
        return True
    else:
        return False

答案 5 :(得分:0)

r_p = re.compile('^(?=\S{6,20}$)(?=.*?\d)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[^A-Za-z\s0-9])')

此代码将使用以下命令验证您的密码:

  1. 最小长度为6,最大长度为20
  2. 至少包含一个数字,
  3. 至少一个小写字母和一个小写字母
  4. 至少一个特殊字符

答案 6 :(得分:-1)

如果len条件为false,则代码仅执行else语句。解决这个问题:

更紧凑的版本,你可以这样做:

if len(data) >= 10 and any(i in data for i in digs) and (i in data for i in alphaupper) and (i in data for i in alphalower):