gpt4 book ai didi

How to type annotate reduce function?(如何输入注解归约函数?)

转载 作者:bug小助手 更新时间:2023-10-25 19:09:05 28 4
gpt4 key购买 nike



I'm writing a very thin wrapper on top of list and I want to define a method called reduce, but I'm struggling to annotate it properly such that pylance, mypy & pylint cut their complaints whenever I use the method, or even define it.

我在list的顶部写了一个非常薄的包装器,我想定义一个叫做reduce的方法,但是我很难正确地注释它,这样每当我使用这个方法,甚至定义它时,pylance,mypy和pylint都会减少他们的抱怨。


I was perturbed to realize that almost None of Python's builtin libraries are type annotated.

我很不安地意识到,几乎没有一个Python的内置库是带类型注释的。


This is my implementation attempt:

这是我的实现尝试:


    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

This fails when my List is actually a list of strings

当我的List实际上是一个字符串列表时,


a: List[str] = List(['a', 'b'])
b = a.reduce(lambda x, y: x + y)

Obviously here, the type checkers and linters say they expect list[T] while I passed str.

显然,在这里,当我传递str时,类型检查器和链接器说他们期望List[T]。


更多回答
优秀答案推荐

I think in this situation one would use a generic type, otherwise it can't reason about your types fully. Heres an example of a list using a Generic type which supports a Protocol that allows it to be reduced:

我认为在这种情况下,人们会使用泛型类型,否则它不能完全推理您的类型。下面是一个使用泛型类型的列表示例,该泛型类型支持允许减少列表的协议:


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(func, 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)

Some usage of it:

它的一些用法如下:


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

If you tried to use some class which didn't support __add__, mypy would warn you:

如果您尝试使用一些不支持__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)

更多回答

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com