如何正确使用 T=TypeVar('T', bound=...) 和 Type[T] ?
How to use T=TypeVar('T', bound=...) with Type[T] correctly?
我有以下带类型注释的 Django 代码:
from typing import Optional, Type, TypeVar
from django.db import models
T = TypeVar('T', bound=models.Model)
def get_obj_or_none(model: Type[T], obj_id: int) -> Optional[T]:
try:
return model.objects.get(pk=obj_id)
except model.DoesNotExist:
return None
该函数需要一个从 django.db.models.Model
派生的 class 作为第一个参数,一个 int
id 作为第二个参数:
# obj is now the Person with id 123, or None if that didn't exist.
obj = get_obj_or_none(Person, 123)
但是当我在代码上运行 mypy 时,我得到错误:
error: "Type[T]" has no attribute "objects"
error: "Type[T]" has no attribute "DoesNotExist"
但是,如果将我的代码更改为此并再次 运行 mypy,我不会收到任何错误:
from typing import Optional, Type
from django.db import models
def get_obj_or_none(model: Type[models.Model], obj_id: int) -> Optional[models.Model]:
try:
return model.objects.get(pk=obj_id)
except model.DoesNotExist:
return None
为什么第一个示例不起作用?我真的更喜欢使用它,因为第二个示例没有以任何方式将 return 值绑定到 model
参数,因此该函数可能是 returning 一个实例,即与作为第一个参数给出的 class 完全无关。
我正在使用 Python 3.8.1 和 mypy 0.761。
编辑:
这是一个独立的示例,可以按原样进行测试:
from typing import Dict, Optional, Type, TypeVar
class Model:
objects: Dict[int, 'Model'] = {}
T = TypeVar('T', bound=Model)
def get_obj_or_none(model: Type[T], obj_id: int) -> Optional[T]:
try:
return model.objects[obj_id]
except KeyError:
return None
运行 mypy 给出了(令我惊讶的)一个完全不同的错误:
type_example.py:17: error: Incompatible return value type (got "Model", expected "Optional[T]")
Found 1 error in 1 file (checked 1 source file)
为什么 mypy 在这两个例子中表现不同?我能以某种方式解决这两种情况吗?
第一个示例在设置 django-stubs for my project. Good instructions can be found from 后正常工作。
最后一个示例正确给出了 mypy 的错误,因为 Python 不允许这样做。套用 a GitHub issue 我打开了:
The objects attribute can contain an instance of an arbitrary Model
subclass, but the return type of get_obj_or_none
contains a specific subtype T
of Model
. Type[T]
has no effect in this example, since the type of the objects
attribute is the same in subclasses (it doesn't use a "self" type). I don't think that there's a way to use a self type for a class variable.
我有以下带类型注释的 Django 代码:
from typing import Optional, Type, TypeVar
from django.db import models
T = TypeVar('T', bound=models.Model)
def get_obj_or_none(model: Type[T], obj_id: int) -> Optional[T]:
try:
return model.objects.get(pk=obj_id)
except model.DoesNotExist:
return None
该函数需要一个从 django.db.models.Model
派生的 class 作为第一个参数,一个 int
id 作为第二个参数:
# obj is now the Person with id 123, or None if that didn't exist.
obj = get_obj_or_none(Person, 123)
但是当我在代码上运行 mypy 时,我得到错误:
error: "Type[T]" has no attribute "objects" error: "Type[T]" has no attribute "DoesNotExist"
但是,如果将我的代码更改为此并再次 运行 mypy,我不会收到任何错误:
from typing import Optional, Type
from django.db import models
def get_obj_or_none(model: Type[models.Model], obj_id: int) -> Optional[models.Model]:
try:
return model.objects.get(pk=obj_id)
except model.DoesNotExist:
return None
为什么第一个示例不起作用?我真的更喜欢使用它,因为第二个示例没有以任何方式将 return 值绑定到 model
参数,因此该函数可能是 returning 一个实例,即与作为第一个参数给出的 class 完全无关。
我正在使用 Python 3.8.1 和 mypy 0.761。
编辑:
这是一个独立的示例,可以按原样进行测试:
from typing import Dict, Optional, Type, TypeVar
class Model:
objects: Dict[int, 'Model'] = {}
T = TypeVar('T', bound=Model)
def get_obj_or_none(model: Type[T], obj_id: int) -> Optional[T]:
try:
return model.objects[obj_id]
except KeyError:
return None
运行 mypy 给出了(令我惊讶的)一个完全不同的错误:
type_example.py:17: error: Incompatible return value type (got "Model", expected "Optional[T]") Found 1 error in 1 file (checked 1 source file)
为什么 mypy 在这两个例子中表现不同?我能以某种方式解决这两种情况吗?
第一个示例在设置 django-stubs for my project. Good instructions can be found from
最后一个示例正确给出了 mypy 的错误,因为 Python 不允许这样做。套用 a GitHub issue 我打开了:
The objects attribute can contain an instance of an arbitrary
Model
subclass, but the return type ofget_obj_or_none
contains a specific subtypeT
ofModel
.Type[T]
has no effect in this example, since the type of theobjects
attribute is the same in subclasses (it doesn't use a "self" type). I don't think that there's a way to use a self type for a class variable.