Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.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';s类型提示,指示返回值与参数';s型_Python_Type Hinting_Typing - Fatal编程技术网

如何动态使用Python';s类型提示,指示返回值与参数';s型

如何动态使用Python';s类型提示,指示返回值与参数';s型,python,type-hinting,typing,Python,Type Hinting,Typing,我正在使用Python从磁盘读取JSON,并试图确保我的类型提示在下游是正确的。例如,类似这样的内容: 输入导入列表中的 def verify_包含_int(项目:列表[object])->列表[int]: 对于项目中的项目: 如果不存在(项目,int): raise TypeError(“列表内容必须为所有整数”) 退货项目 我遇到的问题是,我不想为int、bool、str等编写单独的函数。有没有办法动态指定要验证的类型?我想写的是这样的: 输入导入列表中的 def verify_包含_类型

我正在使用Python从磁盘读取JSON,并试图确保我的类型提示在下游是正确的。例如,类似这样的内容:

输入导入列表中的

def verify_包含_int(项目:列表[object])->列表[int]:
对于项目中的项目:
如果不存在(项目,int):
raise TypeError(“列表内容必须为所有整数”)
退货项目
我遇到的问题是,我不想为int、bool、str等编写单独的函数。有没有办法动态指定要验证的类型?我想写的是这样的:

输入导入列表中的

def verify_包含_类型(项目:列表[对象],内部_类型=对象)->列表[内部_类型]:
对于项目中的项目:
如果不存在(项目,内部类型):
raise TypeError(f“列表内容必须是所有{INERNAR_type}”)
退货项目
在当前的类型暗示状态下,有没有办法做到这一点


注意:这是我实际要做的事情的简化版本。默认的内部类型在这里可能看起来很傻,但它对我的用例很重要。

我相信您可以在这里使用
类型化。cast
,这有点难看。注意,它没有运行时效果,它只是返回传递给它的内容,尽管它确实会产生函数调用开销。但它告诉类型检查器“现在是这种类型”。您应该使用
TypeVar
使其成为泛型,然后像您试图做的那样简单地传递类型,并用
type

from typing import List, TypeVar, Type, cast

T = TypeVar('T')
def verify_contains_type(items: List[object], inner_type: Type[T]) -> List[T]:
    for item in items:
        if not isinstance(item, inner_type):
            raise TypeError("List contents must be all ints")
    return cast(List[T], items)


mylist: List[object] = [1, 2, 3, 4]

safe_mylist: List[int] = verify_contains_type(mylist, int)
print(safe_mylist[0] + safe_mylist[1])
mypy现在很高兴:

(py38) juan$ mypy --version
mypy 0.750
(py38) juan$ mypy test_typing.py
Success: no issues found in 1 source file

是的,但前提是您可以构建新列表:

从键入导入列表,键入,TypeVar
T=TypeVar('T')
def verify_contains(项目:列表[object],内部_类型:类型[T])->列表[T]:
#Mypy目前需要这个提示来推断什么是“clean_items”
#应该包含。其他类型检查器可能不支持。
清理项目:列表[T]=[]
对于项目中的项目:
如果不存在(项目,内部类型):
raise TypeError(“列表内容必须为所有整数”)
清理项目。追加(项目)
退回清洁物品
如果您不熟悉TypeVar是什么,那么它们是一种让您编写泛型代码的方法。有关更多详细信息,请参阅

类型允许您指定想要的是类对象,而不是类的实例。有关更多详细信息,请参阅


我们需要创建一个新列表的原因是,如果我们不这样做,您可能会由于变异而在代码中引入错误。例如:

original:List[object]=[3,2,1]
all_ints=验证_包含(原始,int)
#法律,因为可疑交易记录是一种客体
原始。附加(“繁荣”)
#…但如果verify_contains未返回副本,则将
#打印出[3,2,1,“boom”]!
打印(所有内容)
如果您不介意忽略这个潜在的bug,请按照其他一些答案的建议使用cast


另一种替代方法可能是使用类似的库,而不是自己编写验证逻辑

这是我个人会采取的方法:我可以专注于使用PEP 484类型编写高级模式,并让库为我处理验证。

添加到,但支持
对象的默认
内部类型
。我能找到的最好方法是结合使用
typing.Union
typing.重载
。我必须承认这相当冗长,但至少不需要对代码进行功能更改

解决方案 在此之后:

mylist: List[object] = [1, 2, 3, 4]

# Revealed type is 'builtins.list[builtins.float*]'
my_floats = verify_contains_type(mylist, float)


# Revealed type is 'builtins.list[builtins.object]'
my_whatevers = verify_contains_type(mylist)
解释 在分析函数的使用情况时,类型检查器将只查看
@重载
函数定义,按指定顺序检查它们,直到找到匹配项。不考虑实际函数中的类型注释

在分析函数本身主体内的代码时,类型检查将只使用实际函数的类型注释,而忽略
@重载
定义

有关过载的附加信息


这看起来很好,只是当我尝试将inner_type默认为object时,人们不知道/不关心该类型,mypy抱怨说。有什么想法吗?这是完美的,除了那一个问题。如果你知道如何将internal_类型设置为object默认值,我会将此设置为可接受的答案:)@micseydel,请参阅我关于internal_类型默认类型的答案。如果这两个人一起回答了你的问题,请接受juanpa。arrivillaga的回答,而不是我的。我还没有花时间完全理解这一点(特别是过载部分),但是
Union[List[t],List[object]
并没有挫败我在这里尝试的目的?@micseydel,不,
Union
不会被类型检查器使用,但我理解这种混淆。我已经添加了一些额外的解释,并且可以推荐Mypy文档来更深入地了解函数重载。这还不是一个答案,但是在python 3.9之后的一段时间,应该可以对参数化泛型进行更好的动态类型检查:
mylist: List[object] = [1, 2, 3, 4]

# Revealed type is 'builtins.list[builtins.float*]'
my_floats = verify_contains_type(mylist, float)


# Revealed type is 'builtins.list[builtins.object]'
my_whatevers = verify_contains_type(mylist)