一、误区
动态/静态类型和强/弱类型分别描述了一门程序语言的不同方面,一门动态类型语言既可能是强类型的,也可能是弱类型的;同样的,一门静态类型语言既可能是强类型的,也可能是弱类型的。
二、定义
-
动态类型(dynamically typed)与静态类型(statically typed):根据变量的类型在其生命周期中是否可以变化判断。
- 静态类型语言中,变量属于一个确定的类型,不可改变,在其整个生命周期中只能引用同一类型的值,如C语言;(变量类型在编译时就固定下来,因此可以实现编译时的类型安全)
- 动态类型语言中,变量的类型并不固定,可以改变(或者描述为类型是绑定到值上的,而不是绑定到变量上的),典型的例子如Python;(变量类型在运行时动态确定)
-
强类型(strongly typed)与弱类型(weakly typed):在这一层面的区分上,大家的分歧会相对大一些。就我个人的理解(供参考,欢迎大佬指正)可以通过以下标准界定:
- 是否允许不同类型的操作数直接运算;当两个操作数类型不一致时,弱类型语言会做更多的隐式类型转换(如不可思议地隐式地将数值转换为字符串),且存在合法的不同类型操作数间的运算,如C语言中允许指针类型与整数类型的算术运算;这里的另一个关键在于直接,强类型语言也可以通过运算符重载的方式间接地允许不同类型间的运算,如Python通过运算符重载(魔术方法)支持列表类型与整型数据的乘法。
- 是否存在能够越过语言的类型系统,从而可能导致未知后果的操作;如C语言中可以通过强制类型转换,让指针的基类型与所指变量的类型不同。
三、示例
1.Python是动态类型、强类型语言
def ret_int():
return 666
def ret_str():
return "laotie"
print("Start")
v = "balabala"
v = 1234
v = []
v1, v2 = ret_int(), ret_str()
print(v1 + v2)
print("End")
- 动态类型:变量v的数据类型在运行时动态地改变;在编译时并不固定变量类型,无法实现编译时类型安全,仅能保证运行时类型安全。正如上例中,只有当代码实际运行到了
print(v1 + v2)
这一行时,才做类型检查,才会报错。 - 强类型:不支持不同类型的变量间进行运算操作,除非显式地进行类型转换或是通过魔术方法对操作进行定义(或者说为运算符重载);
2.C语言是静态类型、弱类型语言
#include <stdio.h>
int main() {
printf("Start\n");
int i = 0;
// i = 3.14;
const int Refresh = 90;
printf("Refresh %c\n", Refresh);
char s[6] = "Hello";
int *intp = (int *)s;
printf("i = %d\n", *(intp + 2));
printf("End\n");
}
- 静态类型:声明变量的同时需要声明变量类型,且变量的整个生命周期类型固定,只能用来保存相同类型的值(
i = 3.14;
会在编译时报错); - 弱类型:类型的限制并不严格,比如
printf("Refresh %c\n", Refresh)
用字符格式打印整型常量;int *intp = (int *)s
用整型指针指向字符;printf("i = %d\n", *(intp + 2))
指针类型与整数进行算术运算;