Мне действительно нравится использовать опцию и любые монады в Scala. Есть ли эквивалент для этих вещей в Python? Если нет, то каков питонический способ обработки ошибок или "отсутствия ценности" без исключения исключений?
Есть ли эквивалент Python для Scala Option или Either?
Ответ 1
Питонический способ для функции сказать: "Я не определен на этом этапе" - вызвать исключение.
>>> int("blarg")
Traceback (most recent call last):
...
ValueError: invalid literal for int() with base 10: 'blarg'
>>> dict(foo=5)['bar']
Traceback (most recent call last):
...
KeyError: 'bar'
>>> 1 / 0
Traceback (most recent call last):
...
ZeroDivisionError: integer division or modulo by zero
Частично это связано с тем, что для python нет (как правило, полезного) средства проверки статического типа. Функция Python не может синтаксически заявить во время компиляции, что она имеет определенный кодомен; нет никакого способа заставить вызывающих абонентов соответствовать всем случаям в типе возврата функции.
Если вы предпочитаете, вы можете написать (нетипично) обертку Maybe
:
class Maybe(object):
def get_or_else(self, default):
return self.vaue if isinstance(self, Just) else default
class Just(Maybe):
def __init__(self, value):
self.value = value
class Nothing(Maybe):
pass
Но я бы не стал этого делать, если вы не пытаетесь перенести что-то из Scala в Python без особых изменений.
Ответ 2
mypy
добавляет определения типов и проверку типов (не во время выполнения) поверх обычного Python. У них есть Optional
: https://docs.python.org/3/library/typing.html#typing.Optional. Подробнее здесь https://www.python.org/dev/peps/pep-0484/#rationale-and-goals. Intellij имеет поддержку плагинов, что делает его очень профессиональным и плавным.
Ответ 3
В python, при отсутствии значения, переменная имеет значение None, поэтому вы можете сделать это таким образом.
vars = None
vars = myfunction()
if vars is None:
print 'No value!'
else:
print 'Value!'
или даже просто проверьте, присутствует ли это значение
if vars is not None:
print vars
Ответ 4
Я понимаю, что это довольно поздно для вечеринки, но я пришел на эту страницу поверх google, прежде чем принимать решение о ее реализации, поэтому, возможно, я могу помочь другим пользователям поработать с этим. Я реализовал его, вы можете получить его из pypi как pyther-maybe
, он реализует как Либо, так и Может быть с помощью Maybe в качестве специального подкласса Либо. Этот пример должен объяснить, как это работает:
import sys
from pyther_maybe import *
def save_div ( x, y ):
if y == 0:
return nothing() # alias of Maybe()
else:
return value(x / y) # alias of Maybe(x / y)
float_test = save_div(1.0, 3.0)
assert isinstance(float_test, Maybe)
if float_test: #nothing tests as false:
float = float_test() # calling the container with no arguments returns its value
else:
sys.exit("something went wrong")
print float
# or if you want to encode a reason:
def save_div ( x, y ):
if y == 0:
return left("You can't divide by zero, silly") # alias of Either(left=...)
else:
return right(x / y) # alis of Either(...)
float_test = save_div(4.2, 0.0)
assert isinstance(float_test, Either)
def fake_exit ( string ):
print "We would have exited with:"
print string
return "Whatever value"
if float_test:
# these two are te same
float = float_test()
float = float_test.right()
else:
fake_exit(float_test.left())
# or in a shorter and more pleasant format
# does the same as above
float = float_test.extract(fake_exit)
print float # prints "Whatever value"
# Also, these containers are mutable:
box = nothing()
try:
print box() # raises exception
except RightEitherException:
print "We caught an exception"
def change_box():
box(4)
change_box()
print box() # 4
У него есть больше возможностей, чем некоторые, некоторые из которых на практике практически бесполезны (например, он также итератор и имеет нотацию под индексом, например pyther_maybe.either(x)[pyther_maybe.Right] == x
.
Ответ 5
Список, который всегда имеет нулевую длину или один, выполняет некоторые из тех же целей, что и необязательные/может быть типы. Вы не получите преимуществ статической типизации в Python, но вы, вероятно, получите ошибку во время выполнения даже на счастливом пути, если напишите код, который пытается использовать "возможно" без явного "развертывания" его.