Python 3.5中的类型提示是什么?
Python 3.5中最容易说的功能之一是类型提示。
类型提示的示例“ http://lwn.net/articles/640359/” rel =“ noreferrer”>这个同时还提到要负责任地使用类型提示。有人可以解释更多有关它们的信息,什么时候应该使用它们,何时不使用它们?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我建议阅读 pep 483 和 pep 484 并观看此介绍 guido type minting。
简而言之:类型提示实际上是单词的含义。您暗示您使用的对象的类型。
由于python的动态性质,推断或检查所使用的对象的类型尤其困难。这个事实使开发人员很难理解他们尚未编写的代码中的确切情况,最重要的是,对于许多IDE中找到的类型检查工具( pycharm 和
要从类型提示演示文稿中获取两个重要幻灯片:
为什么键入提示
typeerrors
。。
,并弹出了未针对对象定义的方法/属性。为什么要使用静态类型的检查器?
动态语言缺乏。您的应用程序越大,越复杂,则变得越多(从
您需要的行为方面)。
作为此小简介的闭幕说明:这是可选功能,据我了解,它是为了获得静态键入的一些好处而引入的。 。
通常,您 不需要担心它,肯定不需要使用它(尤其是在使用Python作为辅助脚本语言的情况下)。当开发大型项目时,它应该有帮助,它提供了急需的鲁棒性,控制和其他调试功能。
类型提示使用mypy :
为了使这个答案更加完整,我认为一些演示是合适的。我将使用
mypy
,启发类型提示的库是呈现的。在佩普。这主要是为任何遇到这个问题并想知道从哪里开始的人而写的。在这样做之前,让我重申以下内容: pep 484 任何事物;它只是为功能设定方向
应为的注释和提出指南类型检查应该/应执行。您可以注释您的功能,
提示您想要的尽可能多的东西;无论注释的存在如何,您的脚本仍将运行,因为Python本身不使用它们。
无论如何,如PEP中所述,提示类型通常应采用三种形式:
#类型:类型
注释,与前两种形式相辅相成。 (请参阅: for python 3.6更新##type:type
注释),您还需要与新的
键入
py> py> py3.5
中引入的模块。在其中,许多(额外) abcs (摘要基础类)带有辅助功能和装饰器,用于静态检查。包括collections.abc
中的大多数ABC,但以a generic 表单为允许订阅(通过定义__ getItem __()
方法)。对于对这些更深入的解释感兴趣的任何人,写得很好,并且有很多代码样本演示/描述其检查器的功能;绝对值得一读。
功能注释和特殊评论:
首先,观察使用特殊评论时可以得到的某些行为很有趣。特殊
#类型:类型
评论可以在变量分配期间添加,以指示如果不能直接推断对象的类型。简单的作业是
通常很容易推断,但其他人,例如清单(关于其内容),不能。
注意:如果我们想使用容器的任何衍生物 ,并且需要指定该容器的内容,我们必须 通用 类型
键入
模块。 这些支持索引。如果我们将这些命令添加到文件中并用我们的解释器执行它们,则一切正常,
print(a)
只需打印列表
a
的内容。#类型
注释已被丢弃,被视为没有其他语义含义的普通注释。另一方面,通过使用
mypy
进行此操作,我们得到以下响应:指示
str
对象的列表不包含int
,从静态上讲,这是合理的。可以通过遵守a
的类型来解决这一点,并且仅附加str
对象,也可以通过更改a
的内容的类型来指示。任何值都是可以接受的(之后,使用
已从list [任何]
在直觉上执行任何键入
中导入任何)。函数注释以
param_name形式添加:type
在您的函数签名中的每个参数和使用- &gt指定返回类型之后;
在结束功能结肠之前符号;所有注释都存储在__注释__
该功能的属性中,以方便的字典形式。 不需要键入
模块中的额外类型):注释。
使用琐碎的示例( ,或者我们熟悉Python  2.7概念,因此不知道
typeError
潜伏在注释>注释
的比较中,我们可以执行另一个静态检查,捕获错误并保存。我们有一些麻烦:除其他外,还将以无效的论点调用该功能:
这些功能可以扩展到任何用例,而所捕获的错误比基本的呼叫和操作更远。您的类型
可以检查真的很灵活,我只是赋予其潜力的小潜行峰。在
键入
模块中查看PEPS或
mypy
文档将使您对所提供的功能有更全面的想法。存根文件:
存根文件可以在两种不同的非相互排斥的情况下使用:
存根文件(带有
.pyi
的扩展名)是您要/要使用的模块的注释接口。它们包含您想通过丢弃功能的主体来键入功能的功能的签名。为了感觉到这一点
在名为
randfunc.py
的模块中的三个随机函数中:我们可以创建一个存根文件
randfunc.pyi
,如果我们希望这样做,我们可以放置一些限制。不利的一面是当试图理解所假定的内容时
通过的地方。
无论如何,存根文件的结构非常简单:用空物体添加所有功能定义(
Pass
填充)和根据您的要求提供注释。在这里,我们假设我们只想使用
int
我们的容器类型。combine
函数指出了您为什么要在其他文件中使用注释,它们有时会混乱代码并降低了可读性(Python的大型禁忌)。您当然可以使用类型的别名,但有时会混淆不止于此
帮助(因此明智地使用它们)。
这应该使您熟悉Python中类型提示的基本概念。即使使用的类型检查器已经
mypy
您应该逐渐开始看到更多的弹出窗口,其中一些在IDE中( pycharm )和其他作为标准的python模块。我将尝试在下面的列表中添加其他查看器/相关软件包。
Checkers我知道 :
相关软件包/项目 :
打字
项目实际上是您可以寻找的最佳场所之一,以查看如何在自己的项目中使用类型的提示。让我们以示例____________________________________ >
counter
class的dunders在相应的
.pyi
文件中:其中
进行
_t = typevar('_ t')
用于定义通用类。对于counter
类,我们可以看到它可以在其初始化器中不进行参数,请从任何类型中获取单个映射
em>或以任何类型的。
注意:我忘了提到的一件事是,
键入
模块是在临时基础上引入的。来自 pep 411 :因此,用少许盐将东西带到这里;我怀疑它将以重大的方式将其删除或改变,但人们永远不会知道。
** 完全有效,但在类型含义的范围中有效:
pep 526
:可变注释的语法是一种努力,通过引入新的新注释来替换#type
注释语法允许用户注释简单varname中的变量类型:type
语句。参见 对这些> 进行了较小的介绍。
I would suggest reading PEP 483 and PEP 484 and watching this presentation by Guido on type hinting.
In a nutshell: Type hinting is literally what the words mean. You hint the type of the object(s) you're using.
Due to the dynamic nature of Python, inferring or checking the type of an object being used is especially hard. This fact makes it hard for developers to understand what exactly is going on in code they haven't written and, most importantly, for type checking tools found in many IDEs (PyCharm and PyDev come to mind) that are limited due to the fact that they don't have any indicator of what type the objects are. As a result they resort to trying to infer the type with (as mentioned in the presentation) around 50% success rate.
To take two important slides from the type hinting presentation:
Why type hints?
TypeErrors
..
and having methods/attributes pop up which aren't defined for an object.Why use static type checkers?
dynamic languages lack. The bigger and more complex your application becomes the more control and predictability (from
a behavioral aspect) you require.
As a closing note for this small introduction: This is an optional feature and, from what I understand, it has been introduced in order to reap some of the benefits of static typing.
You generally do not need to worry about it and definitely don't need to use it (especially in cases where you use Python as an auxiliary scripting language). It should be helpful when developing large projects as it offers much needed robustness, control and additional debugging capabilities.
Type hinting with mypy:
In order to make this answer more complete, I think a little demonstration would be suitable. I'll be using
mypy
, the library which inspired Type Hints as they are presented in the PEP. This is mainly written for anybody bumping into this question and wondering where to begin.Before I do that let me reiterate the following: PEP 484 doesn't enforce anything; it is simply setting a direction for function
annotations and proposing guidelines for how type checking can/should be performed. You can annotate your functions and
hint as many things as you want; your scripts will still run regardless of the presence of annotations because Python itself doesn't use them.
Anyways, as noted in the PEP, hinting types should generally take three forms:
# type: type
comments that complement the first two forms. (See: What are variable annotations? for a Python 3.6 update for# type: type
comments)Additionally, you'll want to use type hints in conjunction with the new
typing
module introduced inPy3.5
. In it, many (additional) ABCs (abstract base classes) are defined along with helper functions and decorators for use in static checking. Most ABCs incollections.abc
are included, but in a generic form in order to allow subscription (by defining a__getitem__()
method).For anyone interested in a more in-depth explanation of these, the
mypy documentation
is written very nicely and has a lot of code samples demonstrating/describing the functionality of their checker; it is definitely worth a read.Function annotations and special comments:
First, it's interesting to observe some of the behavior we can get when using special comments. Special
# type: type
commentscan be added during variable assignments to indicate the type of an object if one cannot be directly inferred. Simple assignments are
generally easily inferred but others, like lists (with regard to their contents), cannot.
Note: If we want to use any derivative of containers and need to specify the contents for that container we must use the generic types from the
typing
module. These support indexing.If we add these commands to a file and execute them with our interpreter, everything works just fine and
print(a)
just printsthe contents of list
a
. The# type
comments have been discarded, treated as plain comments which have no additional semantic meaning.By running this with
mypy
, on the other hand, we get the following response:Indicating that a list of
str
objects cannot contain anint
, which, statically speaking, is sound. This can be fixed by either abiding to the type ofa
and only appendingstr
objects or by changing the type of the contents ofa
to indicate that any value is acceptable (Intuitively performed withList[Any]
afterAny
has been imported fromtyping
).Function annotations are added in the form
param_name : type
after each parameter in your function signature and a return type is specified using the-> type
notation before the ending function colon; all annotations are stored in the__annotations__
attribute for that function in a handy dictionary form. Using a trivial example (which doesn't require extra types from thetyping
module):The
annotated.__annotations__
attribute now has the following values:If we're a complete newbie, or we are familiar with Python 2.7 concepts and are consequently unaware of the
TypeError
lurking in the comparison ofannotated
, we can perform another static check, catch the error and save us some trouble:Among other things, calling the function with invalid arguments will also get caught:
These can be extended to basically any use case and the errors caught extend further than basic calls and operations. The types you
can check for are really flexible and I have merely given a small sneak peak of its potential. A look in the
typing
module, thePEPs or the
mypy
documentation will give you a more comprehensive idea of the capabilities offered.Stub files:
Stub files can be used in two different non mutually exclusive cases:
What stub files (with an extension of
.pyi
) are is an annotated interface of the module you are making/want to use. They containthe signatures of the functions you want to type-check with the body of the functions discarded. To get a feel of this, given a set
of three random functions in a module named
randfunc.py
:We can create a stub file
randfunc.pyi
, in which we can place some restrictions if we wish to do so. The downside is thatsomebody viewing the source without the stub won't really get that annotation assistance when trying to understand what is supposed
to be passed where.
Anyway, the structure of a stub file is pretty simplistic: Add all function definitions with empty bodies (
pass
filled) andsupply the annotations based on your requirements. Here, let's assume we only want to work with
int
types for our Containers.The
combine
function gives an indication of why you might want to use annotations in a different file, they some times clutter upthe code and reduce readability (big no-no for Python). You could of course use type aliases but that sometime confuses more than it
helps (so use them wisely).
This should get you familiarized with the basic concepts of type hints in Python. Even though the type checker used has been
mypy
you should gradually start to see more of them pop-up, some internally in IDEs (PyCharm,) and others as standard Python modules.I'll try and add additional checkers/related packages in the following list when and if I find them (or if suggested).
Checkers I know of:
Related Packages/Projects:
The
typeshed
project is actually one of the best places you can look to see how type hinting might be used in a project of your own. Let's take as an example the__init__
dunders of theCounter
class in the corresponding.pyi
file:Where
_T = TypeVar('_T')
is used to define generic classes. For theCounter
class we can see that it can either take no arguments in its initializer, get a singleMapping
from any type to anint
or take anIterable
of any type.Notice: One thing I forgot to mention was that the
typing
module has been introduced on a provisional basis. From PEP 411:So take things here with a pinch of salt; I'm doubtful it will be removed or altered in significant ways, but one can never know.
** Another topic altogether, but valid in the scope of type-hints:
PEP 526
: Syntax for Variable Annotations is an effort to replace# type
comments by introducing new syntax which allows users to annotate the type of variables in simplevarname: type
statements.See What are variable annotations?, as previously mentioned, for a small introduction to these.
添加到吉姆的精心响应答案:
检查
键入
module - 此模块支持类型提示,如 pep 484 。例如,以下功能获取并返回类型
str
的值,并注释如下:键入
模块还支持:Adding to Jim's elaborate answer:
Check the
typing
module -- this module supports type hints as specified by PEP 484.For example, the function below takes and returns values of type
str
and is annotated as follows:The
typing
module also supports:新发布的Pycharm 5支持类型提示。在他们有关它的博客文章中(请参阅 python 3.5在Pycharm 5 中暗示)他们提供了一个很好的解释哪种类型的提示是和不是,以及有关如何在代码中使用它们的几个示例和插图。
此外,它在python 2.7中得到了支持,如此评论:
The newly released PyCharm 5 supports type hinting. In their blog post about it (see Python 3.5 type hinting in PyCharm 5) they offer a great explanation of what type hints are and aren't along with several examples and illustrations for how to use them in your code.
Additionally, it is supported in Python 2.7, as explained in this comment:
类型提示是用于可维护性的,并且不会被Python解释。在下面的代码中,行
def add(self,ic:int)
不会导致错误,直到下一个返回...
line:Type hints are for maintainability and don't get interpreted by Python. In the code below, the line
def add(self, ic:int)
doesn't result in an error until the nextreturn...
line: