【问题标题】:Check every condition in Python if else even if one evaluates to true检查 Python 中的每个条件 if else 即使一个评估为真
【发布时间】:2014-08-09 07:05:17
【问题描述】:

如果判断结果为真,Python 中是否有办法继续检查 if else 语句的条件?这是我的代码:

status = True

  if pass_len(S) == False:
    print ('Password must be at least 6 characters long')
    status = False
  elif pass_upper(S) == False:
    print('Password must include upper case letters')
    status = False
  elif pass_lower(S) == False:
    print('Password must include lower case letters')
    status = False
  elif pass_nums(S) == False:
    print('Password must include digits.')
    status = False
  else:
    status = True

  return status

例如,如果密码没有大写字符或数字,我想打印这两条消息,而不是只打印“密码必须包含大写字母”并在那里结束。我尝试通过从每个语句中取出 return 来解决这个问题,但它没有用。任何帮助表示赞赏,谢谢。

【问题讨论】:

  • 是的,摆脱 elif...
  • 你不需要最后一个else: status = True
  • @ShashankAgarwal,啊,是的!谢谢!

标签: python if-statement


【解决方案1】:

不要使用elif,使用if 将确保检查条件。 elif 只会在 if 语句计算为 False 时检查

In [40]: foo = 3

In [41]: if foo == 3:
   ....:     print (foo)
   ....: if foo != 4:    
   ....:     print ("checked too")
   ....:     
3
checked too

status = True 已经将状态设置为True,所以只需return status 不需要else

【讨论】:

  • 出于好奇,我很想看到它通过按位操作实现(例如finalflags = run_all_the_tests(0),每个测试设置一个位)。我可能会在几个小时内把一些东西放在一起作为练习。
  • @AdamSmith,听起来很有趣!如果您尝试一下,我很乐意看到它。
  • @JoseMagana 完成后我会写下来作为答案
【解决方案2】:

执行此操作的另一种方法更短一些,并且还为您提供了一个列表,其中触发了哪些错误是列表理解:

errors = [message for (has_error, message) in (
    (not pass_len(S), 'Password must be at least 6 characters long'),
    (not pass_upper(S), 'Password must include upper case letters'),
    (not pass_lower(S), 'Password must include lower case letters'),
    (not pass_nums(S), 'Password must include digits.'),
    ) if has_error]

【讨论】:

  • 哦,我真的很喜欢这个。
  • 太棒了。这个我还没学会。感谢分享!
  • 你可以将其重构为RULES = [(pass_len, '...'), (pass_upper, '...'), ...]; errors = [message for test, message in RULES if not test(S)]
  • @Suor 仅当所有未来规则都将在一个参数 S 上运行时
【解决方案3】:

从@JasonS 的优秀答案中恶意窃取,这是我在评论中提到的有点玩弄的方法。

# :: all functions look just like this one! ::
import functools, operator

def pass_len(password, length=6):
    try:
        if len(password) < length:
            return 0b0001
        else:
            return 0
    except Exception as e:
        return 0b0001
# pass_upper returns 0b0010 or 0
# pass_lower returns 0b0100 or 0
# pass_nums  returns 0b1000 or 0

def password_validate(password):
    conditions = [pass_len, pass_upper, pass_lower, pass_nums]
    result = functools.reduce(operator.or_, map(lambda x: x(password), conditions))
    errors = [message for (bitflag, message) in (
        (0b0001, 'Password must be at least 6 characters long'),
        (0b0010, 'Password must include upper case letters'),
        (0b0100, 'Password must include lower case letters'),
        (0b1000, 'Password must include digits.')
        ) if result & bitflag]
    for error in errors:
        print(error)

输出:

>>> password_validate("hunter12")
Password must include upper case letters
>>> password_validate("HUNTER")
Password must include lower case letters
Password must include digits.
>>> password_validate('')
Password must be at least 6 characters long
Password must include upper case letters
Password must include lower case letters
Password must include digits.

您可以通过以下方式进一步干燥:

def password_validator(bitflag):
    def wrap(f):
        def wrapped_f(*args):
            return bitflag if f(*args) else 0
        return wrapped_f
    return wrap

@password_validator(0b0001)
def pass_len(password, length=6):
    return len(password) < length
@password_validator(0b0010)
def pass_upper(password):
    return password.lower() == password
@password_validator(0b0100)
def pass_lower(password):
    return password.upper() == password
@password_validator(0b1000)
def pass_num(password):
    return any(num in password for num in '0123456789')

def password_validate(password):
    # this function is identical to the one above

【讨论】:

  • 哇,一个非常独特的方法来解决这个问题!我对计算机科学很陌生,我想知道:按位运算是软件工程行业的常见用法吗?这看起来很酷。
  • @JoseMagana 查看我的编辑,了解使用装饰器执行此操作的更干燥的方法。按位运算通常要快得多,但可读性要差得多。像任何其他优化一样接近它们——早期优化是魔鬼,但是一旦你分析了你的代码并注意到“哦,这是我的瓶颈”,然后期望花费至少尽可能多的时间来记录和解释你的按位操作作为您希望在接下来的几个月中从中受益的时间:)
  • @JoseMagana 也就是说,由于我的代码实际上并没有对位标志做任何合理的工作,它甚至可能比标准条件慢一点。请注意,如果您使用 Jason 的代码,他会调用每个函数一次,而当您调用我的代码时,我会调用每个函数一次,然后必须稍后检查其输出。这样比较慢。
  • 为什么“if len(password)
  • @kmonsoor 如果您将任何没有定义__len__ 魔术方法的对象传递给它?比如一个数字。或者实际上任何对象由于某些深思熟虑的原因,其__len__ 函数返回的东西不能用数字排序。或者我想如果你把一个同样不可排序的数字扔进length kwarg("Hello World" &lt; [1,2,3,4] 可能会抛出一个TypeError
猜你喜欢
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 2017-11-12
  • 2016-11-27
  • 2014-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多