ScalaでOptionとEitherのモナドを使うのは本当に楽しいです。 Pythonでこれらのものに相当するものはありますか?ない場合、例外をスローせずにエラーまたは「値の不在」を処理するPythonの方法は何ですか?
関数が「現時点では定義されていません」と言うPythonの方法は、例外を発生させることです。
>>> 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の(一般に役立つ)静的型チェッカーがないためです。 A Python function cannotコンパイル時に、特定のコドメインがあることを構文的に示します。関数の戻り値のすべてのケースに一致するように呼び出し元を強制する方法はありませんタイプ。
必要に応じて、Maybe
ラッパーを(非Python的に)作成できます。
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への変更なしで)何かを移植しようとしない限り、私はこれを行いません。
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はプラグインをサポートしており、すべてプロフェッショナルでスムーズに動作します。
Pythonでは、値がない場合、変数はNoneなので、この方法で行うことができます。
vars = None
vars = myfunction()
if vars is None:
print 'No value!'
else:
print 'Value!'
または、このように値が存在するかどうかを確認するだけです
if vars is not None:
print vars
私はこれがパーティーにかなり遅れていることに気づきましたが、私がそれを実装することを決定する前にグーグルの上にこのページに来たので、多分私はこれでグーグルするのを助けることができます。私はそれを実装しました、あなたはpypiから_pyther-maybe
_としてそれを得ることができます、それはEitherとMaybeの両方をEitherの特別なサブクラスとして実装します。この例では、それがどのように機能するかを説明する必要があります。
_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
のような添え字表記があります。
たまたま長さがゼロまたは1のリストは、オプション/たぶんタイプと同じ目標のいくつかを満たします。 Pythonで静的型付けの利点は得られませんが、明示的に「アンラップ」せずに「多分」を使用しようとするコードを記述した場合、ハッピーパスでもランタイムエラーが発生する可能性があります。
これを試して:
from monad import Monad
class Either(Monad):
# pure :: a -> Either a
@staticmethod
def pure(value):
return Right(value)
# flat_map :: # Either a -> (a -> Either b) -> Either b
def flat_map(self, f):
if self.is_left:
return self
else:
return f(self.value)
class Left(Either):
def __init__(self, value):
self.value = value
self.is_left = True
class Right(Either):
def __init__(self, value):
self.value = value
self.is_left = False