用于检查字符串是否为大写但不是方法的函数

时间:2017-12-17 14:45:25

标签: python function oop methods

我正在编写一个程序来检查给定的密码是否至少包含1个大写字母和1个小写字母。我可以很容易地检查这样:

    #Password needs to have at least 1 upper case letter
    has_upper_letter = False
    for letter in password:
        if letter.isupper():
            has_upper_letter = True
            break
    if not has_upper_letter:
        raise forms.ValidationError(_("The password needs to have at least 1 upper case letter"))

    #Password needs to have at least 1 lower case letter
    has_lower_letter = False
    for letter in password:
        if letter.islower():
            has_lower_letter = True
            break
    if not has_lower_letter:
        raise forms.ValidationError(_("The password needs to have at least 1 lower case letter"))

但是这段代码是重复的。我想只在一次检查某种字母的字母时编写逻辑。我的想法是编写一个以isupper()islower()函数为参数的函数。但问题是,isupper()islower()方法作为字符串本身的方法存在。如果我只能得到将我要检查的字符串作为其参数的函数,我的问题就会得到解决。有这样的事吗?随意为我的问题发布更好的解决方案。

3 个答案:

答案 0 :(得分:5)

您可以使用operator.methodcaller(),也可以使用getattr();要么可以用来动态调用方法:

from operator import methodcaller

def matches_test(test, password):
    return any(map(test, password))

has_lower_letter = matches_test(methodcaller('islower'), password)
has_upper_letter = matches_test(methodcaller('isupper'), password)

methodcaller()在传递给它的任何内容上调用命名方法:

>>> from operator import methodcaller
>>> upper = methodcaller('isupper')
>>> upper('ABC')
True
>>> upper('abc')
False

methodcaller()个对象也接受其他参数传入,因此methodcaller('foo', 42)会在您传递给它的任何对象上调用.foo(42)

any() function只是一种(更加紧凑)用for测试和if编写break循环的方式;它遍历您传入的迭代,并停止生成True结果的时刻;如果没有生成True结果,则返回False

getattr()可让您访问变量属性;方法只是你调用的属性:

def matches_test(methodname, password):
    return any(getattr(l, methodname)() for l in password)

has_lower_letter = matches_test('islower', password)
has_upper_letter = matches_test('isupper', password)

您还可以传入未绑定字符串方法,因此str.isupperstr.islower;传入一个新的字符串值就像将该方法绑定到该字符串:

>>> str.isupper('ABC')
True

所以以下内容也有效:

def matches_test(test, password):
    return any(test(l) for l in password)

has_lower_letter = matches_test(str.islower, password)
has_upper_letter = matches_test(str.isupper, password)

答案 1 :(得分:0)

您可以传递lambda表达式:

def check_password(password, f):
   return any(f(i) for i in password)

print(check_password("theString", lambda x:x.isupper()))

或者,将所需的字符串方法传递给函数:

print(check_password("theString", str.isupper))

输出:

True

答案 2 :(得分:0)

解决此问题的另一种方法是使用正则表达式。以下代码将使用以下规则验证密码:

  • 密码必须介于8到16个字符之间
  • 密码必须包含大写和小写字母
  • 密码必须包含数字

代码:

import re

def pswd_check(pswd):
    m=re.match("(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$", pswd)
    return m!=None

if __name__ == "__main__":
    print(pswd_check("testthis"))
    print(pswd_check("t3sttHis"))

输出:

False
True