在JVM语言中,有一种名为Optional的数据类型,它表示值可以为Null / None。通过将函数的数据类型用作Option(例如Option(Int))。调用函数声明可以采取行动。
如何在Python中实现类似的方法。 我想创建一个函数,函数的返回值应该告诉我 1.功能成功,所以我返回了一个值。 2.功能不成功,所以没有任何回报。
答案 0 :(得分:1)
原始问题:提出异常而不是返回None
。这是Python中的一个成语,因此用户很好理解。例如
def get_surname(name):
if name == "Monty":
return "Python"
else:
raise KeyError(name)
您将在Python中看到这种使用模式:
try:
print(get_surname("foo"))
except KeyError:
print("Oops, no 'foo' found")
根据您的反馈,您似乎也希望确保实际使用某些返回值。这非常棘手,我不认为有一种优雅的方法可以在Python中强制执行此操作,但我会尝试一下。
首先,我们将返回值放在属性中,以便我们可以跟踪它是否确实已被读取。
class Result(object):
def __init__(self, value):
self._value = value
self.used = False
@property
def value(self):
self.used = True # value was read
return self._value
其次,我们要求必须在Result
- 块中检索with
对象。退出块(__exit__
)时,我们检查是否已读取该值。为了处理用户没有使用with
- 语句的情况,我们还检查在垃圾收集时是否已读取该值(__del__
)。例外情况将转换为警告。我通常会回避__del__
。
class RequireUsage(object):
def __init__(self, value):
self._result = Result(value)
def __enter__(self):
return self._result
def __exit__(self, type, value, traceback):
if type is None: # No exception raised
if not self._result.used:
raise RuntimeError("Result was unused")
def __del__(self):
if not self._result.used:
raise RuntimeError("Result was unused (gc)")
要使用此系统,只需将返回值包装在RequireUsage
中,如下所示:
def div2(n):
return RequireUsage(n/2)
要使用此类函数,请将它们包装在一个块中并提取value
:
with div2(10) as result:
print(result.value)
如果您未在任何地方调用result.value
,您现在将获得例外:
with div2(10) as result:
pass # exception will be thrown
同样,如果您只是在没有div2
的情况下致电with
,您也会遇到异常:
div2(10) # will also raise an exception
我不会特别推荐真实程序中的这种精确方法,因为我觉得它在使用时增加了很少的使用率。此外,仍然没有覆盖边缘情况,就像您只是执行res = div2(10)
一样,因为保留的引用会阻止__del__
被调用。
答案 1 :(得分:1)
我也想解决这个问题,并建立了一个名为optional.py的图书馆。可以使用pip install optional.py
安装。它已经过全面测试,并支持python2和python3。很乐意提供一些反馈,建议和贡献。
要解决另一个答案的问题并避免任何仇恨,是的,引发异常是python的惯用语,但是,这导致控制流异常与实际异常原因之间的歧义。
关于防止防御性编程的大量讨论掩盖了应用程序的核心逻辑以及对话双方的聪明人。我个人的偏爱是使用可选的,所以我提供了支持该偏爱的库。可以使用异常(或返回None
)作为替代方法,但不是我的偏爱。
答案 2 :(得分:0)
一种方法是返回()
或(<type>,)
(在您的情况下为int
)。然后,您可以提出一些辅助功能,例如:
def get_or_else(option: tuple, default):
if option:
return option[0]
else:
return default
此方法的一个好处是您无需依赖第三方库即可实现此目的。作为对应,您基本上必须创建自己的小图书馆。