如何输入注释reduce函数?

问题描述 投票:0回答:1
我正在

list

 之上编写一个非常薄的包装器,我想定义一个名为 
reduce
 的方法,但我很难正确注释它,以便 
pylance
mypy
pylint
 剪切每当我使用该方法,甚至定义它时,他们都会抱怨。

我很不安地意识到几乎所有 Python 内置库都没有类型注释。

无论如何,这是我的实现,

def reduce(self, func: Callable[[list[T], list[T]], list[T]] = lambda x, y: x + y, default: Optional[T] = None) -> 'List[T]': # type: ignore from functools import reduce if default is None: return List(reduce(func, self.list)) # type: ignore return List(reduce(func, self.list, default)) # type: ignore
当我的 

List

 实际上是字符串列表时,这会失败

a: List[str] = List(['a', 'b']) b = a.reduce(lambda x, y: x + y)
显然在这里,类型检查器和 linter 说他们期望 

list[T]

,而我通过了 
str

python types annotations lint
1个回答
0
投票
我认为在这种情况下,人们会使用

泛型类型,否则它无法完全推理你的类型。下面是一个使用支持reduce的通用类型的列表示例(因为我们强制它有一个 __add__

 方法):

from functools import reduce from typing import Sequence, TypeVar, Callable, Generic, Dict, Protocol, cast A = TypeVar("A") # define that our type supports the add operator, since it needs to be able to to reduce it class SupportsAdd(Protocol[A]): def __add__(self, __other: A) -> A: ... T = TypeVar("T", bound=SupportsAdd) def _reduce_default(x: T, y: T) -> T: return x + y # instead of using None as the default, we use a special object # so that we can distinguish between None and a missing default # # (the underlying reduce function does the same thing) _missing_default = object() class MyList(Generic[T]): def __init__(self, initialdata: Sequence[T]) -> None: self.data = list(initialdata) def __getitem__(self, i: int) -> T: return self.data[i] def __setitem__(self, i: int, v: T) -> None: self.data[i] = v def __len__(self) -> int: return len(self.data) def __delitem__(self, i: int) -> None: del self.data[i] def reduce( self, func: Callable[[T, T], T] = _reduce_default, default: T = cast(T, _missing_default), ) -> T: if default is _missing_default: return reduce(_reduce_default, self.data) else: return reduce(func, self.data, default) # just another method that uses the types def add_keys(self, keys: Dict[T, int]) -> None: for k in keys: self.data.append(k)
它的一些用法:

def test() -> None: ll: MyList[int] = MyList([1, 2, 3]) print(ll[1]) ll[1] = 5 print(ll[1]) # add some keys ll.add_keys({30: 1, 50: 2, 60: 3}) print(len(ll)) val: int # define the type separately, mypy warns us if it doesnt match val = ll.reduce() print(val) # using strings instead ll2: MyList[str] = MyList(["a", "b", "c"]) print(ll2.reduce())
2
5
6
149
abc
如果您尝试使用某些不支持

__add__

的类,
mypy
会警告您:

# test class to see if classes without __add__ fail class NoAdd: def __init__(self, v: int) -> None: self.v = v x: MyList[NoAdd] = [NoAdd(1)]
test.py:100: error: Type argument "NoAdd" of "MyList" must be a subtype of "SupportsAdd[Any]"  [type-var]
test.py:100: error: Value of type variable "T" of "MyList" cannot be "NoAdd"  [type-var]
Found 2 errors in 1 file (checked 1 source file)
    
© www.soinside.com 2019 - 2024. All rights reserved.