python中可选对象的实现
optional.p的Python项目详细描述
可选.py
python可选对象的实现
为什么
作为空的None
和作为错误结果的None
之间存在差异。一个常见的坏习惯是
返回None
表示缺少某些内容。这样做会在代码中引入歧义。
例如:
thing=stuff.getSomeThing().getAnotherThing()
如果getsomething的结果返回None
,会发生什么?我们会得到一个AttributeError: 'NoneType' object has no attribute 'getAnotherThing'
。
你能做些什么来防止这种例外?你可以防御性地写作:
something=stuff.getSomeThing()ifsomethingisnotNone:thing=something.getAnotherThing()
然而,如果我们加入到我们的链中,你可以想象防御性检查的嵌套是如何迅速累积起来的。这些防御检查混淆了我们的实际业务逻辑,降低了可读性。 此外,防御检查是一个容易出错的过程,因为很容易忘记检查所需的条件。
因此,我们提供一个可选的对象作为替代。
安装
与python 2和3都兼容!
$ pip install optional.py
用法
您可以使用:
fromoptionalimportOptional
您可以将其设置为空:
代替::尖叫猫:
returnNone
你可以:微笑猫:
returnOptional.empty()
或
returnOptional.of()
您可以将其设置为包含以下内容:
代替::尖叫猫:
return"thing"
你可以:微笑猫:
returnOptional.of("thing")
您可以检查它是否存在:
代替::尖叫猫:
ifthingisnotNone:
你可以:微笑猫:
thing=some_func_returning_an_optional()ifthing.is_present():
或者::傻笑猫:
thing=some_func_returning_an_optional()ifthing:
您可以检查它是否为空:
代替::尖叫猫:
ifthingisNone:
你可以:微笑猫:
thing=some_func_returning_an_optional()ifthing.is_empty():
或者::傻笑猫:
thing=some_func_returning_an_optional()ifnotthing:
您可以得到值:
代替::尖叫猫:
print(thing)
你可以做::傻笑猫:
thing=some_func_returning_an_optional()...print(thing.get())
但这不是使用此库的推荐方法。
如果为空,则无法获取该值:
而不是::哭猫脸:
ifthingisNone:print(None)# very odd
你可以做::傻笑猫:
thing=some_func_returning_an_optional()ifthing.is_empty():print(thing.get())# **will raise an exception**
但这将引发异常!
您可以获取默认值:
而不是::哭猫脸:
thing=some_func_may_return_none()ifthingisNone:thing='23'
或::尖叫猫:
thing=Optional.of(some_func_may_return_none())ifthing.is_empty():thing='23'else:thing=thing.get()
你可以做::傻笑猫:
thing=Optional.of(some_func_may_return_none()).get_or_default('23')
您可以让'u或'u raise在消失时引发任何异常:
代替::尖叫猫:
try:thing=some_func_returning_an_optional()returnthing.get()exceptOptionalAccessOfEmptyException:raiseMyCustomException()
你可以做:心眼猫:
returnsome_func_returning_an_optional().get_or_raise(MyCustomException())
最佳使用:您可以在状态下链接:
代替::尖叫猫:
ifthingisnotNone:print(thing)
你可以做:心眼猫:
thing=some_func_returning_an_optional()thing.if_present(lambdathing:print(thing))
最佳用法:您可以在不存在时链接:
代替::尖叫猫:
ifthingisnotNone:print(thing)else:print("PANTS!")
你可以做:心眼猫:
thing=some_func_returning_an_optional()thing.if_present(lambdathing:print(thing)).or_else(lambda_:print("PANTS!"))
注意,这里的lambda可以换成实际的函数名。
最佳使用:您可以在不存在的情况下运行供应商:
代替::尖叫猫:
thing=some_func_returning_an_empty_optional()ifthing.is_empty():thing=Optional.of("pants")print(thing.get())# Prints "pants"
你可以做:心眼猫:
defsome_supplier():return"pants"thing=some_func_returning_an_empty_optional().or_else(some_supplier)print(thing.get())# Prints "pants"
最佳使用:您可以在不在场的情况下提出:
代替::尖叫猫:
ifthingisNone:raiseSomeException("Boom!")
你可以做:心眼猫:
thing=some_func_returning_an_optional()thing.if_present(lambdathing:print(thing)).or_else_raise(SomeException("Boom!"))
最佳用法:您可以映射函数::心眼猫:
defmapping_func(thing):returnthing+"PANTS"thing_to_map=Optional.of("thing")mapped_thing=thing_to_map.map(mapping_func)# returns Optional.of("thingPANTS")
注意如果映射函数返回
None
,那么映射调用将返回Optional.empty()
。阿尔索 如果对空的可选项调用map
,它将返回Optional.empty()
。最佳用法:您可以展开映射一个函数,该函数已返回一个可选的::心眼猫:
defflat_mapping_func(thing):returnOptional.of(thing+"PANTS")thing_to_map=Optional.of("thing")mapped_thing=thing_to_map.map(mapping_func)# returns Optional.of("thingPANTS")
注意这不会返回可选的。使用此用于返回选项的映射函数。 如果与此一起使用的映射函数不返回可选值,则调用
flat_map
将引发FlatMapFunctionDoesNotReturnOptionalException
。您可以比较两个选项::smile_cat:
Optional.empty()==Optional.empty()# TrueOptional.of("thing")==Optional.of("thing")# TrueOptional.of("thing")==Optional.empty()# FalseOptional.of("thing")==Optional.of("PANTS")# False
测试
有完整的测试覆盖率,它们在python 2和3中都通过了测试。
运行单元测试
首先,使用:
在test_requirements.txt
中安装需求
$ pip install -r test_requirements.txt
您可以使用:
$ pytest
测试覆盖率
您可以使用:
$ pytest --cov=optional test/
$ coverage report