python几种设计模式,适用于多种条件的Python设计模式

What is the recommended structure to write validate functions with many conditions? See these two examples. The first looks ugly, the second isn't very common, perhaps because assert is generally used to rule out unexpected behaviour. Are there better alternatives?

def validate(val):

if cond1(val):

return False

if cond2(val):

return False

if cond3(val)

return False

return True

Or

def validate(val):

try:

assert cond1(val)

assert cond2(val)

assert cond3(val)

return True

except AssertionError:

return False

解决方案

A compact way to write that function is to use any and a generator expression:

def validate(val):

conditions = (cond1, cond2, cond3)

return not any(cond(val) for cond in conditions)

The any and all functions short-circuit, so they'll stop testing as soon as they have a definite result, i.e., any stops as soon as it hits a True-ish value, all stops as soon as it hits a False-ish value, so this form of testing is quite efficient.

I should also mention that it's much more efficient to pass a generator expression like this to all / any than a list comprehension. Because all / any stop testing as soon as they get a valid result, if you feed them from a generator then the generator will stop too, thus in the above code if cond(val) evaluates to a True-ish value no further conditions will be tested. But if you pass all / any a list comprehension, eg any([cond(val) for cond in conditions]) the whole list has to be be built before all / any can even start testing.

You haven't shown us the internal structure of your cond functions, but you did mention assert in your question, so I feel that the following remarks are in order here.

As I mentioned in the comments, assert should not be used to validate data, it's used to validate program logic. (Also, assertion-handling can be disabled via an -O command line option). The correct Exception to use for data with invalid values is ValueError, and for objects that are the wrong type, use TypeError. But bear in mind that exceptions are designed to handle situations that are exceptional.

If you expect a lot of malformed data then it's generally more efficient to use if based logic than exceptions. Python exception-handling is quite fast if the exception isn't actually raised, in fact it's faster than the equivalent if based code. However, if the exception is raised say more than 5-10% of the time, then the try...except based code will be noticeably slower than the if based equivalent.

Of course, sometimes using exceptions is the only sensible option, even though the situation isn't all that exceptional. A classic example is when you're converting a collection of numeric strings to actual numeric objects, so that strings that represent integers get converted to integer objects, other numeric strings get converted to floats, and other strings get left as strings. The standard way to do this in Python involves using exceptions. For example:

def convert(s):

''' Convert s to int or float, if possible '''

try:

return int(s)

except ValueError:

try:

return float(s)

except ValueError:

return s

data = ['42', 'spam', '2.99792458E8']

out = [convert(u) for u in data]

print(out)

print([type(u) for u in out])

output

[42, 'spam', 299792458.0]

[, , ]

Using "Look Before You Leap" logic here is possible here, but it makes the code more complicated because you need to deal with possible minus signs and scientific notation.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值