类型
Python 是动态类型语言,并且引以为傲。我当然不希望对类型的“圣战”煽风点火,但同时肯定有大学派认为构建可靠的应用程序需要有比只使用单元测试更加有力的保障。Benjamin Pierce对类型系统的定义如下:
...一种易于处理的语法,通过根据计算值的类型对词组分类证明了缺少了特定的程序行为
重点是证明有关运行空间的属性, 所有程序行为的运行空间替代了只是简单地罗列有限种情况的运行空间。全静态类型对于Python是否是正确的选择让人十分疑惑,但是在过度的动态类型和静态类型保证之间肯定有更加合适的方案。MyPy project找到了一个不错的平衡点,允许有类型的和没有类型的代码能够同时存于语言的超集中。例如:
def simple_typed(x : int, y : int) -> int:
return x + y
simple_typed(1, 2) # Type-checks succesfully
# Fails: Argument 2 to "simple_typed" has incompatible type # "float"
simple_typed(1, 2.0)
# Fails: Argument 2 to "simple_typed" has incompatible type "str"
simple_typed(1, "foo")
当然对C语言没有太多的用处。所以我们不只限于简单类型的函数,参数类型也有泛型,指针类型和各种各样内建的类型级的函数。
from typing import Iterator, typevar, Generic, Function, List
T = typevar('T')
def example_typed(x : Iterator[int]) -> Iterator[str]:
for i in x:
yield str(i)
def example_generic(x : Iterator[T]) -> Iterator[T]:
for i in x:
yield i
我们也能定义更加高级的泛型结构例如函子和单元
a = typevar('a')
b = typevar('b')
class Functor(Generic[a]):
def __init__(self, xs : List[a]) -> None:
self._storage = xs
def iter(self) -> Iterator[a]:
return iter(self._storage)
def fmap(f : Function[[a], b], xs : Functor[a]) -> Functor[b]:
return Functor([f(x) for x in xs.iter()])
class Monad(Generic[a]):
def __init__(self, val : a) -> None:
self.val = val
class IdMonad(Monad):
# Monad m => a -> m a
def unit(self, x : a) -> Monad[b]:
return IdMonad(x)
# Monad m => m a -> (a -> m b) -> m b
def bind(self, x : Monad[a], f : Function[[a], Monad[b]]) -> Monad[b]:
return f(x.val)
# Monad m => m (m a) -> m a
def join(self, x : Monad[Monad[a]]) -> Monad[a]:
return x.val