在另一个泛型类型中使用泛型类型的参数

问题描述 投票:0回答:1

标题可能有点含糊,因为我不确定如何准确地表达我想要做的事情。

我想在 python 中从 C++ 复制类似的模式:

template<typename T>
struct Foo
{
    using t = T;  // Alias T so it can be used in Bar
};


template<typename T>
struct Bar
{
    // The type T from Foo<T> can be used as a return type here
    typename T::t fn()
    {
        // do something that returns T::t
    }
};

int main(){
    // x is determined to be a float
    auto x = Bar<Foo<float>>().fn();
};

就Python而言,我想用另一个专用类型

Bar[T]
专门化通用类型
Foo[T]
,然后使用用于专门化
Foo
的类型在
Bar
中输入提示。

类似的东西

from typing import TypeVar, Generic

T = TypeVar("T")

class Foo(Generic[T]):
    ...

class Bar(Generic[Foo[T]]): # <-- This is illegal
    def fn(self) -> T:
        ...

# In the following, I would like the type checker to know that x is an int.
x = Bar[Foo[int]]().fn()

我知道,如果我们有类似

的东西,那么在创建 
Bar

的实例时可以推断出这种关系
class Bar(Generic[T]):
    def __init__(self, foo: Foo[T]):
        ...

但这并不真正适合我当前的问题。

我宁愿能够创建一个专业化系列

Foo[T]
Bar[T]
Baz[T]
等,而无需多次重复
T
。 在我的实际用例中,类型更像
Foo[R, S, T]
并且重复类型非常乏味且容易出错,并且从概念上讲,类
Bar
Baz
等被认为不依赖于类型
T
但而是一种特殊类型的
Foo[T]

所以如果有能力做类似的事情就好了

MyFoo = Foo[int]
MyBar = Bar[MyFoo]
MyBaz = Baz[MyFoo]
python python-typing
1个回答
3
投票

阅读 mypy 文档,我发现了这一点:自我类型的高级用途

通过在

TypeVar
中使用以
Foo
为边界的
Bar
,我们可以指定
Bar
由类似
Foo
的东西参数化。 然后,在各个方法中,我们可以使用嵌套类型
self
注释
Bar[Foo[T]]
,从而使
T
绑定到参数化
Foo
参数化
Bar
的参数。

from __future__ import annotations
from typing import TypeVar, Generic

T = TypeVar("T")

class Foo(Generic[T]):
    ...

# You may want to make `S` covariant with `covariant=True` 
# if you plan on using subclasses of `Foo` as parameters to `Bar`.
S = TypeVar("S", bound=Foo)

class Bar(Generic[S]):
    def fn(self: Bar[Foo[T]]) -> T:
        ...

# Below, when binding `fn`, `self` is recognized as 
# being of type `Bar[Foo[int]]` which binds `T` as `int` 
# and hence the return type is also `int`.
x = Bar[Foo[int]]().fn()

我一直无法弄清楚的是如何使用

Bar
中的参数
T
来注释
Bar[Foo[T]]
的属性。 类似的东西

class Bar(Generic[Foo[T]]):  # Still invalid.
    item: T

sill 不起作用。

但是,可以通过将属性包装在属性中来解决这个问题

class Bar(Generic[S]):
    _item: Any
    
    @property
    def item(self: Bar[Foo[T]]) -> T:
        return self._item

以类型提示

_item
不精确为代价。

© www.soinside.com 2019 - 2024. All rights reserved.