Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否可以使用Mypy为fold_left()指定一个类型?_Python_Mypy - Fatal编程技术网

Python 是否可以使用Mypy为fold_left()指定一个类型?

Python 是否可以使用Mypy为fold_left()指定一个类型?,python,mypy,Python,Mypy,我有一个简单的左折叠函数,如下所示: 输入import-Iterable、Callable、Optional、TypeVar、重载 S=类型变量(“S”) T=类型变量(“T”) def fold_left(it:Iterable[S],f:Callable[[T,S],T],init:Optional[T]=None)->T: it=国际热核实验堆(iter) 如果init为None: 尝试: acc=下一个(it) 除停止迭代外: raise VALUE ERROR(“左折叠,给定无初始的空

我有一个简单的左折叠函数,如下所示:

输入import-Iterable、Callable、Optional、TypeVar、重载
S=类型变量(“S”)
T=类型变量(“T”)
def fold_left(it:Iterable[S],f:Callable[[T,S],T],init:Optional[T]=None)->T:
it=国际热核实验堆(iter)
如果init为None:
尝试:
acc=下一个(it)
除停止迭代外:
raise VALUE ERROR(“左折叠,给定无初始的空iterable”)
其他:
acc=init
对我来说:
acc=f(acc,i)
返回acc
Mypy在检查该代码时抛出以下错误:

10: error: Incompatible types in assignment (expression has type "T", variable has type "S")
13: error: Incompatible types in assignment (expression has type "T", variable has type "S")
13: error: Argument 1 has incompatible type "S"; expected "T"
15: error: Incompatible return value type (got "S", expected "T")
Mypy似乎不喜欢这样一个事实,即当
init为None
时,类型S和t将是相同的。有没有办法欺骗代码,使其正确地键入check

我尝试使用以下行重载,但没有效果:

@重载
def fold_left(it:Iterable[S],f:Callable[[T,S],T],init:T)->T:
...
@超载
def fold_left(it:Iterable[S],f:Callable[[S,S],S])->S:
...

这个问题分为两部分

首先,对函数的外部接口进行类型检查。这就是与
过载相关的地方

@重载
def fold_left(it:Iterable[S],f:Callable[[T,S],T],init:T)->T:
...
@超载
def fold_left(it:Iterable[S],f:Callable[[S,S],S])->S:
...
这将指定函数的所有有效签名

但这(直接)无助于函数的类型检查。我们需要独立解决这个问题

def fold_left(it: Iterable[S], f: Callable[[T, S], T], init: Optional[T] = None) -> T:
    # we can't change the type of it which is already defined to be an 
    # `Iterable`, so in order for `next` to type check we need a new 
    # variable of type `Iterator` 
    itor: Iterator[S] = iter(it) 

    # acc contains or return value it therefore has to be of type `T`
    acc: T

    if init is None:
        try:
            # mypy isn't smart enough to figure out that if `init` is 
            # `None`, then `S` is equal to `T`, we therefore need to tell it
            # that this assignment is correct
            acc = cast(T, next(itor)) 
        except StopIteration:
            raise ValueError("fold_left given empty iterable with no init")
    else:
        acc = init

    for i in itor:
        acc = f(acc, i)

    return acc

重载
语句确实间接地帮助了我们,因为它们限制了我们函数的公共接口,使我们能够推断我们在实现中使用的
强制转换
是正确的。

这个问题有两个部分

首先,对函数的外部接口进行类型检查。这就是与
过载相关的地方

@重载
def fold_left(it:Iterable[S],f:Callable[[T,S],T],init:T)->T:
...
@超载
def fold_left(it:Iterable[S],f:Callable[[S,S],S])->S:
...
这将指定函数的所有有效签名

但这(直接)无助于函数的类型检查。我们需要独立解决这个问题

def fold_left(it: Iterable[S], f: Callable[[T, S], T], init: Optional[T] = None) -> T:
    # we can't change the type of it which is already defined to be an 
    # `Iterable`, so in order for `next` to type check we need a new 
    # variable of type `Iterator` 
    itor: Iterator[S] = iter(it) 

    # acc contains or return value it therefore has to be of type `T`
    acc: T

    if init is None:
        try:
            # mypy isn't smart enough to figure out that if `init` is 
            # `None`, then `S` is equal to `T`, we therefore need to tell it
            # that this assignment is correct
            acc = cast(T, next(itor)) 
        except StopIteration:
            raise ValueError("fold_left given empty iterable with no init")
    else:
        acc = init

    for i in itor:
        acc = f(acc, i)

    return acc

重载
语句确实间接地帮助了我们,因为它们以某种方式限制了我们函数的公共接口,允许我们推断我们在实现中使用的
强制转换
是正确的。

acc
(type
t
)不会与
it
(type
Iterable[S]
)中的值的类型相同不管例如,
fold_left([1,2,3,4],add)
将返回类型为
int
的值,
[1,2,3,4]
是包含类型为
int
的值的iterable,在许多情况下,
T
S
是同一类型。
acc
仅在未指定
init
时才是
S
类型。如果指定了
init
acc
可以是另一种类型。考虑下面的行,其中代码< >代码>列表[INT] 和<代码> ACC 类型为<代码> STR >:<代码> FordDeLead([1, 2, 3),lambda x,y:x+STR(y),“”)“∧=>123”< /Cord>超载是IMO的去路。这有什么问题?请注意,
mypy
不能假定
T
s
是相同的。静态键入意味着所有
T
S
(包括
T!=S
)的代码必须正确,而不是任何
T
S
(不包括
T!=S
的代码)。函数本身必须具有良好的类型,而不考虑一些具体的、动态的
f
init
值将其限制为有效的行为。那么
acc
(type
t
)是否与
it
(type
Iterable[S]
)中的值具有相同的类型呢?例如,
fold_left([1,2,3,4],add)
将返回类型为
int
的值,
[1,2,3,4]
是包含类型为
int
的值的iterable,在许多情况下,
T
S
是同一类型。
acc
仅在未指定
init
时才是
S
类型。如果指定了
init
acc
可以是另一种类型。考虑下面的行,其中代码< >代码>列表[INT] 和<代码> ACC 类型为<代码> STR >:<代码> FordDeLead([1, 2, 3),lambda x,y:x+STR(y),“”)“∧=>123”< /Cord>超载是IMO的去路。这有什么问题?请注意,
mypy
不能假定
T
s
是相同的。静态键入意味着所有
T
S
(包括
T!=S
)的代码必须正确,而不是任何
T
S
(不包括
T!=S
的代码)。函数本身必须具有良好的类型,而不考虑某些具体的动态
f
init
值将其限制为有效行为。