Python 在定义变量的时候不用指明具体的的类型, 解释器会在运行的时候会自动检查变量的类型, 并根据需要进行隐式的类型转化, 因为 Python 是动态语言, 所以一般情况下是不推荐进行类型转化的.
比如进行 "+" 操作时, 如果加号两边是数据就进行加法操作, 如果两边是字符串就进行字符串连接操作, 如果两边是列表就进行合并操作, 甚至可以进行复数的运算.
解释器会在运行时根据两边的变量的类型调用不同的内部方法. 当加号两边的变量类型不一样的时候, 又不能进行类型转化, 就会抛出 TypeError 的异常.
types 模块从 Python2 到 Python3 的变化
在实际的开发中, 为了提高代码的健壮性, 我们还是需要进行类型检查的. 而进行类型检查首先想到的就是用 types(), 比如使用 types 判断一个 int 类型:
- Source Code:
- #!/usr/bin/env python2.6
- #Author: nock.chen
- from types import *
- mylist = ['nock', 100, '100', 'IT']
- def delete(mylist, item):
- if type(item) is IntType:
- mylist.remove(item)
- delete(mylist, 100)
- print(mylist)
- Result:
- ['nock', '100', 'IT']
我们在 types 模块中可以找到一些常用的类型, 在 2.6.9 中显示的结果:
- types.BooleanType # bool 类型
- types.BufferType # buffer 类型
- types.BuiltinFunctionType # 内建函数, 比如 len()
- types.BuiltinMethodType # 内建方法, 指的是类中的方法
- types.ClassType # 类类型
- types.CodeType # 代码块类型
- types.ComplexType # 复数类型
- types.DictProxyType # 字典代理类型
- types.DictType # 字典类型
- types.DictionaryType # 字典备用的类型
- types.EllipsisType # Ellipsis 类型
- types.FileType # 文件类型
- types.FloatType # 浮点类型
- types.FrameType # 框架对象的类型
- types.FunctionType # 函数类型
- types.GeneratorType # 通过调用生成器函数生成的 generator-iterator 对象类型
- types.GetSetDescriptorType # 用 PyGetSetDef(如 FrameType) 在扩展模块中定义的对象的类型
- types.InstanceType # 实例类型
- types.IntType # int 类型
- types.LambdaType # lambda 类型
- types.ListType # 列表类型
- types.LongType # long 类型
- types.MemberDescriptorType # 在扩展模块中定义的对象类型, 包括 PyMemberDef, 如 datetime.timedelta.days
- types.MethodType # 方法类型
- types.ModuleType # module 类型
- types.NoneType # None 类型
- types.NotImplementedType # NotImplemented 的类型
- types.ObjectType # object 类型
- types.SliceType # slice() 返回的对象类型
- types.StringType # 字符串类型
- types.StringTypes # 一个包含 StringType 和 UnicodeType 的序列, 用于方便对任何字符串对象进行检查.
- types.TracebackType # 在 sys.exc_traceback 中发现的 traceback 对象的类型.
- types.TupleType # 元组类型
- types.TypeType # 类型本身
- types.UnboundMethodType # 另一个名字 for MethodType
- types.UnicodeType # Unicode 字符字符串的类型 (例如, u ' spam)
- types.XRangeType # xrange() 返回的范围对象的类型
官网介绍: https://docs.python.org/2/library/types.html
到了 Python3 版本, types 模块方法已经明显减少了很多, 具体如下:
- types.BuiltinFunctionType
- types.BuiltinMethodType # 内置函数的类型, 如 len() 或 sys.exit(), 以及内置类的方法.(这里,"内置" 的意思是 "用 C 写".)
- types.CodeType # 通过 compile() 返回的代码对象类型.
- types.DynamicClassAttribute
- types.FrameType # 框架对象的类型, 如在 tb 中发现的. tb_frame 如果 tb 是一个 traceback 对象.
- types.FunctionType
- types.GeneratorType # 由生成器函数创建的 generator - iterator 对象类型.
- types.GetSetDescriptorType # 用 PyGetSetDef(如 FrameType) 在扩展模块中定义的对象的类型.
- types.LambdaType # 由 lambda 表达式创建的用户定义函数和函数的类型.
- types.MappingProxyType
- types.MemberDescriptorType
- types.MethodType # 用户定义类实例的方法类型.
- types.ModuleType
- types.SimpleNamespace
- types.TracebackType # traceback 对象的类型, 如 sys.exc_info()
- types.new_class
- types.prepare_class
官网介绍: https://docs.python.org/3/library/types.html#module-types
不推荐使用 type 检查类型
从上面的 Python2 到 Python3 的版本升级过程中, types 模块方法有所减少. 如果使用 type 方法也会存在如下问题:
如上所示说明 i 和 n 的类型是不一样的, 而实际上 UserInt 是继承 int 的, 所以这个判断是存在问题的, 当我们对 Python 内建类型进行扩展的时候, type 返回的结果就不够准确了. 我们再看一个例子:
type 比较的结果 a 和 b 的类型是一样的, 结果明显是不准确的. 这种古典类的实例, type 返回的结果都是一样的, 而这样的结果不是我们想要的. 对于内建的基本类型来说, 使用 tpye 来检查是没有问题的, 可是当应用到其他场合的时候, type 就显得不可靠了.
这个时候我们就需要使用内置函数 isinstance 来进行类型检查, 示例如下:
isinstance(object, class_or_type_or_tuple)
object 表示对象, classinfo 可以是直接或间接类名, 基本类型或者有它们组成的元组.
nock:ucode nock$ python3
- Python 3.5.1 (default, Dec 26 2015, 18:08:53)
- [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
- >>> isinstance(2, float)
- False
- >>> isinstance(2, int)
- True
- >>> isinstance((2, 3), list)
- False
- >>> isinstance((2, 3), tuple)
- True
- >>> isinstance({'name': 'nock'}, tuple)
- False
- >>> isinstance({'name': 'nock'}, dict)
- True
- >>> isinstance([1, 100, 101], (str, list, tuple))
- True
- >>> isinstance(2 ** 31, dict)
- False
- >>> isinstance(2 ** 31, long)
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'long' is not defined
- >>> isinstance(2 ** 31, int)
- True
Python2 有为非浮点数准备的 int 和 long 类型. int 类型的最大值不能超过 sys.maxint, 而且这个最大值是平台相关的. 可以通过在数字的末尾附上一个 L 来定义长整型, 显然, 它比 int 类型表示的数字范围更大. 在 Python3 里, 只有一种整数类型 int, 大多数情况下, 它很像 Python2 里的长整型. 由于已经不存在两种类型的整数, 所以就没有必要使用特殊的语法去区别他们, 进一步阅读: PEP 237 https://www.python.org/dev/peps/pep-0237/ .
来源: https://juejin.im/post/5b2c684b51882574b72f0f39