Vau*_*ein 216 python type-hinting python-3.x python-3.5
__CODE__
据说其中一个被谈到的功能__CODE__
.
的例子__CODE__
本中提到的文章和这同时也提到使用类型负责任提示.有人可以解释更多关于它以及什么时候应该使用它什么时候不使用?
Jim*_*ard 290
我建议阅读PEP 483和PEP 484和观看该演示由Guido的类型提示.
简而言之:类型提示实际上就是单词的意思,你暗示了你正在使用的对象的类型.
由于Python 的动态特性,推断或检查正在使用的对象的类型尤其困难.这一事实使得开发人员很难理解他们未编写的代码到底发生了什么,最重要的是,许多IDE中的类型检查工具[PyCharm,PyDev浮现在脑海中]由于以下事实而受到限制:它们没有任何关于物体类型的指示.因此,他们试图推断出类型(如演示文稿中所述)大约50%的成功率.
从类型提示演示中获取两个重要的幻灯片:
TypeErrors
..
并且弹出了没有为对象定义的方法/属性.作为这个小介绍的结束语:这是一个可选功能,据我所知,它是为了获得静态类型的一些好处而引入的.
你一般不会需要担心它,绝对不需要使用它(尤其是在你使用Python作为辅助脚本语言的情况下).在开发大型项目时应该会有所帮助,因为它提供了非常需要的稳健性,控制和额外的调试功能.
为了使这个答案更加完整,我认为一点点演示是合适的.我将使用mypy
,这个图书馆启发了类型提示,因为它们在PEP中呈现.这主要是针对任何碰到这个问题并想知道从哪里开始的人写的.
在此之前,请允许我重申以下内容:PEP 484不执行任何操作; 它只是为功能注释设置方向,并为如何 /应该执行类型检查提出指导.您可以注释您的功能并提示您想要的任意数量; 无论是否存在注释,您的脚本仍将运行,因为Python本身不使用它们.
无论如何,如PEP所述,提示类型通常应采用三种形式:
# type: type
评论补充前两种形式.(请参阅:Python 3.6中的哪些变量注释?用于注释的Python 3.6更新# type: type
)此外,您还需要将类型提示与typing
引入的新模块结合使用Py3.5
.在其中,定义了许多(附加的)ABC(抽象基类)以及用于静态检查的辅助函数和装饰器.大多数ABCs
在collections.abc
被包括在内,但在一个Generic
形式,以允许订阅(通过定义一个__getitem__()
方法).
对于任何对这些内容有更深入解释感兴趣的人来说,mypy documentation
编写得非常好,并且有很多代码示例演示/描述了他们的检查器的功能; 绝对值得一读.
首先,观察使用特殊注释时可以获得的一些行为很有意思.# type: type
如果无法直接推断,则可以在变量赋值期间添加特殊注释以指示对象的类型.简单的分配通常很容易推断,但其他的,如列表(关于其内容),则不能.
注意:如果我们想要使用任何衍生产品Containers
并且需要指定该容器的内容,我们必须使用模块中的泛型类型typing
.这些支持索引.
# generic List, supports indexing.
from typing import List
# In this case, the type is easily inferred as type: int.
i = 0
# Even though the type can be inferred as of type list
# there is no way to know the contents of this list.
# By using type: List[str] we indicate we want to use a list of strings.
a = [] # type: List[str]
# Appending an int to our list
# is statically not correct.
a.append(i)
# Appending a string is fine.
a.append("i")
print(a) # [0, 'i']
Run Code Online (Sandbox Code Playgroud)
如果我们将这些命令添加到文件并使用我们的解释器执行它们,一切正常,print(a)
只需打印列表的内容a
.这些# type
评论已被废弃,被视为没有额外语义含义的简单评论.
mypy
另一方面,通过运行此操作,我们得到以下响应:
(Python3)jimmi@jim: mypy typeHintsCode.py
typesInline.py:14: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
Run Code Online (Sandbox Code Playgroud)
指示str
对象列表不能包含int
,静态地说,它是声音.这可以通过遵守a
仅附加str
对象的类型或通过更改内容的类型来固定,a
以指示任何值都是可接受的(使用List[Any]
after Any
导入后直观地执行typing
).
函数注释param_name : type
在函数签名中的每个参数之后添加在表单中,并且使用-> type
结束函数冒号之前的符号指定返回类型; 所有注释都__annotations__
以便利的字典形式存储在该函数的属性中.使用一个简单的例子(不需要typing
模块中的额外类型):
def annotated(x: int, y: str) -> bool:
return x < y
Run Code Online (Sandbox Code Playgroud)
该annotated.__annotations__
属性现在具有以下值:
{'y': <class 'str'>, 'return': <class 'bool'>, 'x': <class 'int'>}
Run Code Online (Sandbox Code Playgroud)
如果我们是一个完整的noobie,或者我们熟悉Py2.7
概念并因此不知道TypeError
潜伏在比较中annotated
,我们可以执行另一个静态检查,捕获错误并为我们节省一些麻烦:
(Python3)jimmi@jim: mypy typeHintsCode.py
typeFunction.py: note: In function "annotated":
typeFunction.py:2: error: Unsupported operand types for > ("str" and "int")
Run Code Online (Sandbox Code Playgroud)
除此之外,调用具有无效参数的函数也会被捕获:
annotated(20, 20)
# mypy complains:
typeHintsCode.py:4: error: Argument 2 to "annotated" has incompatible type "int"; expected "str"
Run Code Online (Sandbox Code Playgroud)
这些可以扩展到基本上任何用例,并且捕获的错误比基本调用和操作进一步扩展.你可以检查的类型非常灵活,我只是给它潜在的一个小的潜行峰值.通过查看typing
模块,PEP或mypy
文档,您可以更全面地了解所提供的功能.
存根文件可用于两种不同的非互斥情况:
哪些存根文件(扩展名为.pyi
)是您正在/想要使用的模块的带注释的接口.它们包含要对丢弃的函数体进行类型检查的函数的签名.为了感觉到这一点,给定一个名为的模块中的三个随机函数randfunc.py
:
def message(s):
print(s)
def alterContents(myIterable):
return [i for i in myIterable if i % 2 == 0]
def combine(messageFunc, itFunc):
messageFunc("Printing the Iterable")
a = alterContents(range(1, 20))
return set(a)
Run Code Online (Sandbox Code Playgroud)
我们可以创建一个存根文件randfunc.pyi
,如果我们愿意,我们可以在其中设置一些限制.缺点是有人在没有存根的情况下查看源代码时,在尝试理解应该传递到哪里时,将不会真正获得注释帮助.
无论如何,存根文件的结构非常简单:使用空体(pass
填充)添加所有函数定义,并根据您的要求提供注释.在这里,我们假设我们只想使用int
容器的类型.
# Stub for randfucn.py
from typing import Iterable, List, Set, Callable
def message(s: str) -> None: pass
def alterContents(myIterable: Iterable[int])-> List[int]: pass
def combine(
messageFunc: Callable[[str], Any],
itFunc: Callable[[Iterable[int]], List[int]]
)-> Set[int]: pass
Run Code Online (Sandbox Code Playgroud)
该combine
函数指示了为什么您可能希望在不同的文件中使用注释,它们有时会使代码混乱并降低可读性(Python的大禁忌).你当然可以使用类型别名,但有时混淆比它更有帮助(所以明智地使用它们).
这应该让您熟悉Python中类型提示的基本概念.即使使用了类型检查器,
mypy
您应该逐渐开始看到更多弹出窗口,一些内部在IDE(PyCharm)中,另一些在内部作为标准python模块.如果我找到它们(或者如果建议的话),我会尝试在以下列表中添加其他检查器/相关包.
我知道的跳棋:
相关软件包/项目:
该typeshed
项目实际上是您可以查看如何在您自己的项目中使用类型提示的最佳位置之一.我们以相应文件中类的__init__
dundersCounter
为例.pyi
:
class Counter(Dict[_T, int], Generic[_T]):
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, Mapping: Mapping[_T, int]) -> None: ...
@overload
def __init__(self, iterable: Iterable[_T]) -> None: ...
Run Code Online (Sandbox Code Playgroud)
在哪里_T = TypeVar('_T')
用于定义泛型类.对于Counter
类,我们可以看到它可以在其初始化程序中不接受任何参数,Mapping
从任何类型获取单个int
或接受Iterable
任何类型.
注意:我忘记提到的一件事是该typing
模块是临时引入的.从PEP 411:
临时包可以在"逐渐"进入"稳定"状态之前修改其API.一方面,这种状态为包提供了正式成为Python发行版的一部分.另一方面,核心开发团队明确指出,不会对包的API的稳定性做出任何承诺,这可能会在下一个版本中发生变化.虽然这被视为不太可能的结果,但如果对其API或维护的担忧证明是有充分理由的话,甚至可以在没有弃用期的情况下从标准库中删除此类包.
所以带着一点盐在这里拿东西; 我怀疑它会在很大程度上被移除或改变,但人们永远不会知道.
**另一个主题完全但在类型提示的范围内有效PEP 526
::变量注释的语法是# type
通过引入允许用户在简单varname: type
语句中注释变量类型的新语法来替换注释的努力.
请参阅Python 3.6中的什么是变量注释?如前所述,对于这些介绍的小介绍.
tsv*_*son 25
新发布的PyCharm 5支持类型提示.在他们关于它的博客文章中(参见PyCharm 5中的Python 3.5类型提示),它们提供了关于什么类型提示的很好解释,并没有提供有关如何在代码中使用它们的几个示例和插图.
此外,它在Python 2.7中受支持,如本评论中所述:
PyCharm支持PyPI for Python 2.7,Python 3.2-3.4的输入模块.对于2.7,您必须将类型提示放在*.pyi存根文件中,因为函数注释是在Python 3.0中添加的.
归档时间: |
|
查看次数: |
92418 次 |
最近记录: |