【原文地址:https://xiaokang2022.blog.csdn.net/article/details/126936985】
一个不会写好的类型标注和注释的Python程序员,是让使用TA的代码的人都痛苦无比的事情……
—— 某某大佬
想必大部分现代的集成开发环境(IDE)都有代码智能感知功能吧!
智能感知(IntelliSense),就是在我们写代码的时候,代码编辑器自动弹出我们代码中需要补全的部分,而这些补全的部分就是代码编辑器通过智能感知得到的,最重要的是,代码编辑器智能地感知补全的部分是通过代码中的变量的类型来得到的。
说了这么多之后,大家一定都清楚智能感知是什么了,但有些时候,代码却没有智能感知(如下)

当代码量很大的时候,代码的智能感知是十分重要的,它可以帮你迅速了解到这个变量那个变量是个什么东西,以减少你生产BUG!
写一个好的注释(或者类型标注),不仅仅是方便未来复用你代码的人,也是为了自己,实际上,“为了自己”可不只是简单的方便自己了解代码,更多的是让IDE智能地感知到你的代码,IDE理解了你的代码,它就会为你提供对应的信息(如代码补全和提示作用),这对程序员是极其友好的!
通过了解后面的类型标注和特殊的注释,你将解决几乎所有的智能感知失效的问题!
Python的类型标注有几种,在下面我给出我所知道的一些
1 def function(num: int, string: str):
2 pass
在上面的代码中,函数参数的后面跟了一个冒号和一个类名,代表参数的数据类型,这个类名可以是内置的类,如str、int、float等,也可以是自己定义的类、也可以是模块、库中的类,如tkinter.Tk
num参数是int类型的,string参数是str类型的,这些类型标注不仅仅在函数被定义的地方可以被看见,在调用该函数的时候也能通过IDE的智能感知而被看见(如下)
这个类型标注之后,并不会强制该参数使用该类型,它只是起提示作用,相当于注释,同时,IDE会通过智能感知该类型标注,给出相应的代码提示
1 import typing
2
3 def function(num: int,
4 lis: list[int],
5 key: typing.Literal[4, 5, 6],
6 string: str | None = '123'):
7 pass
上面的代码中:
list[int] 的意思是,lis参数的数据类型为一个内含整数数据的列表类型
typing是一个官方的内置模块,专门用于类型标注,typing.Literal[4, 5, 6] 表示参数key的预期值只能为4或者5或者6,也就是说,该函数接收的key参数,它只希望它是4、5或者6这三个值中的一个
str | None 的意思是,string参数的数据类型可以为str或者是None类型,此处说明一下,类型标注中用 “|” 代表或者的这种操作是在 Python3.10 的时候才加入的,在之前的版本中,这种用法只在 pyi 文件(Python存根文件)中可以用
下面的代码提示中,我们就能看到类似于上面的类型标注的作用

顺便一提,那个省略号(三个连续的小数点)的意思的默认值(一般用于pyi存根文件中)
1 def pow(m: int, n: int) -> int:
2 return m**n
函数返回值的类型标注类似于上面所说的参数类型标注,只不过这里标注的类型只的是函数的返回值的数据类型,同样的,只起提示作用,没有强制效果
这个标注也有高级用法,与上面的完全,一样,此处不再赘述
顺便一提,list[int, int, int] 表示一个含有三个整数数据的列表类型
传言有一种从天而降的写法,不知大家见过没有
1 key: int
2 key = 3
3
4 """
5 或者这样写:
6 key: int = 3
7 """
8
9 print(key) # 输出3
这个变量名后面加一个冒号、再加一个类名的写法也是类型标注的一种,只不过它不是函数的参数,而是一般变量而已,用法同上
那么,这个类型标注有什么用呢?直接赋值给该变量一个列表,那么IDE不也能识别它么?
这对于一般的变量确实没啥用,但是,下面的这种操作,你可看好了
上面的这种情况,当变量没有提前做好类型标注时,后面写代码就因为没有IDE的提示而极其麻烦
变量的类型标注还有一种方法,将在后面的 特殊的注释 中讲到
一段看似普通的注释,实际也有着特殊的作用,就像C#中的特殊注释一样(三条斜杠“///”),Python也有着它特殊的注释
想必一个合格的Python程序员,都知道三引号注释的特殊作用吧
它不仅仅是一段普通的注释,它可以换行(都知道的),它写在函数和类下面表示帮助文档等等……这里就不再赘述了
它只能单行注释……除此之外难道它还有别的特性???对!别的特性!
当 # 注释以这样一种格式写的时候,它有着和类型标注同样的效果!!!
1 key = [] # type: list[float]
# 注释后面写上 type,再加一个冒号、然后加上数据类型,它就成了类型标注!!!
是不是大多数人都不知道这个特性呢?
有一些比较特别的数据类型,有些不是内置的但又算是内置的,但你又不容易找到它,比如迭代器类型、生成器类型、函数类型(Python里函数实际也是个对象,也有类型)等等,下面给出一个表格方便大家进行类型的标注
| 类型名称 | 数据类型 | 引用方式 |
| 函数 | function |
function types.FunctionType |
| 方法 | method |
types.MethodType |
| 迭代器 | Iterator |
typing.Iterator collections.abc.Iterator |
| 生成器 | Generator |
typing.Generator collections.abc.Generator |
| 序列 | Sequence |
typing.Sequence collections.abc.Sequence |
【看了这么多,是不是感觉又涨知识了呢?那么,你的赞呢?】
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳