Python 通过其自身的解释器来进行类型检查。由于 Python 是一门动态语言,它不会强制用户为对象指定类型,这可能导致漏洞,错误也更难排查。为了解决这个问题,可以将 Python 与多种工具配合使用,在保留其鸭子类型特性的同时,引入静态类型检查。
不同的编程语言采用两种不同的类型系统,如下所示。
静态类型语言
动态类型语言
静态类型语言
变量类型的检查在编译期完成。此外,语言的类型系统会强制在使用变量之前显式声明其“数据类型”。静态类型的编程语言包括:Scala、Java、C++ 等。 例如,Scala 中字符串的声明如下:var myCar:String = "Mercedes"; 上述代码表明变量名“myCar”被显式声明为“String”类型,值为“Mercedes”。
动态类型语言
变量类型的检查在运行期完成。此外,语言的类型系统不会强制在使用变量之前显式声明其“数据类型”。动态类型的编程语言包括:Python、JavaScript、Ruby 等。 例如,Python 中字符串的定义如下:myCar = "Mercedes" 上述代码表明变量名“myCar”无需显式声明类型。
Python 中的 'type()' 与 'isinstance()'
可以使用 Python 自带的 'type()' 来获知变量类型。'type()' 可在运行期用于调试,以识别程序中的精确变量类型。来看下面示例中一些变量的类型。
my_var = 12
print ( type ( my_var) )
技术支持
上述代码的输出为 'int'。因为该变量的数据类型是整数,而 'type()' 起到了识别的作用。
Python 的 'insinstance('obj','class')' 可用于判断对象 'obj' 是否是某个类的实例。返回值为布尔类型 True 或 False。
my_var = "Hello"
print ( isinstance ( my_var, str ) )
技术支持
上述代码的输出为 True。因为变量的数据类型为字符串,'isinstance()' 起到了识别的作用。
Python 中的鸭子类型
在 Python 中有一个广为人知的原则:“如果它看起来像鸭子,游起来像鸭子,叫起来也像鸭子,那么它很可能就是鸭子。”该原则的含义很简单:对象或类的具体类型并不重要,只要对象包含相同的方法和属性,就可以将其用于特定目的。 下面通过一个示例更详细地说明上述说法。
看下面的例子,这里有两个类“Duck”和“Human”。Duck 类包含方法 quack 和 fly。类似地,Human 类也有自己的 'quack' 和 'fly' 方法。Duck 和 Human 是不同的类,也是不同的对象或类型。然而,Human 含有与 Duck 相同的 'fly' 和 'quack' 方法。还有一个方法 'fly_quack',它更像是针对“Duck”的,因为它可以飞也可以叫。
class Duck :
def quack ( self) :
print ( 'Quack' )
def fly ( self) :
print ( 'Flap' )
class Human :
def quack ( self) :
print ( 'Trying to Quack like a duck' )
def fly ( self) :
print ( 'Spreading my arm to flap like a duck' )
def fly_quack ( thing) :
thing. quack( )
thing. fly( )
技术支持
让我们创建一个 Duck 的实例 du,并传给函数 'fly_quack(du)'。同样地,创建一个 Human 的实例 'h' 并传给函数 'fly_quack(h)'。
du = Duck( )
fly_quack( du)
h = Human( )
fly_quack( h)
技术支持
上述代码的输出如下:
Trying to Quack like a duck
Spreading my arm to flap like a duck
Quack
Flap
技术支持
虽然“Human”与“Duck”是不同的类,但 Python 也会为 Human 调用函数 'fly_quack'。尽管对象类型不同,只要“Human”具有类似的 quack 和 fly 方法,它就会按预期行为并提供所需的方法。
类型提示与 mypy
像 Python 这样的动态类型语言有一个强大的方面:有助于提高代码的可访问性和可读性,但也存在一些缺点。其中一个缺点是在运行时发现错误,因为 Python 不强制变量类型,或者说它是动态类型语言。其结果可能产生错误与漏洞,且在代码规模越来越大时更难发现。
从 3.5 版本开始,Python 引入了类型提示(Type Hints)。更早的版本可能不支持类型提示功能。
下面先看一个没有类型提示和 mypy 的简单示例。
下面的函数用于整数的减法运算,它应当减去两个整数并返回值。
def sub_this ( x, y) :
return 'Subtraction'
print ( sub_this( 8 , 'hello' ) )
技术支持
这里的函数需要接收两个整数“x”和“y”,但由于未施加约束,可以接收任意数据类型。同时,返回值也可以是任何类型,代码返回了字符串 'Subtraction',而期望的是 'int'。
下面用类型提示和 'mypy' 来实现与上面相似的程序,这可以帮助进行静态类型检查,并更轻松地减少程序中的错误与漏洞。
'mypy' 是一个 Python 模块,用于进行静态类型检查,它结合了 Python 自身的动态检查(鸭子类型)与类型提示。
您需要安装 'mypy' 包 pip install mypy
您可以在本地创建一个名为 'mypy_example.py' 的文件,并输入以下代码。 下面的代码是一个简单程序,在参数中接收两个整数作为输入,'->' 后面标注返回的数据类型同样是 'int'。然而,该函数本应返回 int,却返回了字符串 'Subtracted two integers'。
def sub_this ( x: int , y: int ) - > int :
return 'Subtracted two integers'
print ( sub_this( 8 , 4 ) )
技术支持
在终端中用以下命令运行上述代码。
mypy mypy_example. py技术支持
随后会显示错误,指示发现了意外的返回值 "str",需要改为 "int"。
将返回类型改为两个整数的相减,使其返回整数值。
def sub_this ( x: int , y: int ) - > int :
return x - y
print ( sub_this( 8 , 4 ) )
技术支持
上述结果显示已打印成功信息,未发现问题。
恭喜您
恭喜您,已完成本教程的全部内容!
在本教程中,您了解了类型检查、不同语言的类型系统,以及 Python 方法('type()' 与 'isinstance()')、Python 的鸭子类型,以及结合 'mypy' 的类型提示。
如果您想进一步学习 Python,请查看 DataCamp 的 Software Engineering for Data Scientists in Python 。
参考资料:
Corey 的 YouTube 视频:Duck Typing
Python 通过其自身的解释器来进行类型检查。由于 Python 是一门动态语言,它不会强制用户为对象指定类型,这可能导致漏洞,错误也更难排查。为了解决这个问题,可以将 Python 与多种工具配合使用,在保留其鸭子类型特性的同时,引入静态类型检查。
不同的编程语言采用两种不同的类型系统,如下所示。
静态类型语言
变量类型的检查在编译期完成。此外,语言的类型系统会强制在使用变量之前显式声明其“数据类型”。静态类型的编程语言包括:Scala、Java、C++ 等。
例如,Scala 中字符串的声明如下:
var myCar:String = "Mercedes";上述代码表明变量名“myCar”被显式声明为“String”类型,值为“Mercedes”。
动态类型语言
变量类型的检查在运行期完成。此外,语言的类型系统不会强制在使用变量之前显式声明其“数据类型”。动态类型的编程语言包括:Python、JavaScript、Ruby 等。
例如,Python 中字符串的定义如下:
myCar = "Mercedes"上述代码表明变量名“myCar”无需显式声明类型。
Python 中的 'type()' 与 'isinstance()'
可以使用 Python 自带的 'type()' 来获知变量类型。'type()' 可在运行期用于调试,以识别程序中的精确变量类型。来看下面示例中一些变量的类型。
上述代码的输出为 'int'。因为该变量的数据类型是整数,而 'type()' 起到了识别的作用。
Python 的 'insinstance('obj','class')' 可用于判断对象 'obj' 是否是某个类的实例。返回值为布尔类型 True 或 False。
上述代码的输出为 True。因为变量的数据类型为字符串,'isinstance()' 起到了识别的作用。
Python 中的鸭子类型
在 Python 中有一个广为人知的原则:“如果它看起来像鸭子,游起来像鸭子,叫起来也像鸭子,那么它很可能就是鸭子。”该原则的含义很简单:对象或类的具体类型并不重要,只要对象包含相同的方法和属性,就可以将其用于特定目的。
下面通过一个示例更详细地说明上述说法。
看下面的例子,这里有两个类“Duck”和“Human”。Duck 类包含方法 quack 和 fly。类似地,Human 类也有自己的 'quack' 和 'fly' 方法。Duck 和 Human 是不同的类,也是不同的对象或类型。然而,Human 含有与 Duck 相同的 'fly' 和 'quack' 方法。还有一个方法 'fly_quack',它更像是针对“Duck”的,因为它可以飞也可以叫。
让我们创建一个 Duck 的实例 du,并传给函数 'fly_quack(du)'。同样地,创建一个 Human 的实例 'h' 并传给函数 'fly_quack(h)'。
上述代码的输出如下:
虽然“Human”与“Duck”是不同的类,但 Python 也会为 Human 调用函数 'fly_quack'。尽管对象类型不同,只要“Human”具有类似的 quack 和 fly 方法,它就会按预期行为并提供所需的方法。
类型提示与 mypy
像 Python 这样的动态类型语言有一个强大的方面:有助于提高代码的可访问性和可读性,但也存在一些缺点。其中一个缺点是在运行时发现错误,因为 Python 不强制变量类型,或者说它是动态类型语言。其结果可能产生错误与漏洞,且在代码规模越来越大时更难发现。
从 3.5 版本开始,Python 引入了类型提示(Type Hints)。更早的版本可能不支持类型提示功能。
下面先看一个没有类型提示和 mypy 的简单示例。
下面的函数用于整数的减法运算,它应当减去两个整数并返回值。
这里的函数需要接收两个整数“x”和“y”,但由于未施加约束,可以接收任意数据类型。同时,返回值也可以是任何类型,代码返回了字符串 'Subtraction',而期望的是 'int'。
下面用类型提示和 'mypy' 来实现与上面相似的程序,这可以帮助进行静态类型检查,并更轻松地减少程序中的错误与漏洞。
'mypy' 是一个 Python 模块,用于进行静态类型检查,它结合了 Python 自身的动态检查(鸭子类型)与类型提示。
您需要安装 'mypy' 包
pip install mypy您可以在本地创建一个名为 'mypy_example.py' 的文件,并输入以下代码。
下面的代码是一个简单程序,在参数中接收两个整数作为输入,'->' 后面标注返回的数据类型同样是 'int'。然而,该函数本应返回 int,却返回了字符串 'Subtracted two integers'。
在终端中用以下命令运行上述代码。
随后会显示错误,指示发现了意外的返回值 "str",需要改为 "int"。
将返回类型改为两个整数的相减,使其返回整数值。
上述结果显示已打印成功信息,未发现问题。
恭喜您
恭喜您,已完成本教程的全部内容!
在本教程中,您了解了类型检查、不同语言的类型系统,以及 Python 方法('type()' 与 'isinstance()')、Python 的鸭子类型,以及结合 'mypy' 的类型提示。
如果您想进一步学习 Python,请查看 DataCamp 的 Software Engineering for Data Scientists in Python。
参考资料: