Подтвердить что ты не робот

Есть ли эквивалент Python для Scala Option или Either?

Мне действительно нравится использовать опцию и любые монады в Scala. Есть ли эквивалент для этих вещей в Python? Если нет, то каков питонический способ обработки ошибок или "отсутствия ценности" без исключения исключений?

4b9b3361

Ответ 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, но вы, вероятно, получите ошибку во время выполнения даже на счастливом пути, если напишите код, который пытается использовать "возможно" без явного "развертывания" его.