# 静态类型与动态类型

”静态类型“与”动态类型“，则是对一门编程语言是否在编译期就能确定变量类型的区分。例如，考虑下面这段伪代码：

```
a = 1
a = true
```

在 Python 这样的动态类型语言中，不规定变量类型必须不变，因此类似这样的代码是正确的。而在 Java、C#、TypeScript 等编程语言中，这样的代码是不能通过编译的。这就是对静态类型语言和动态类型语言的简单区分。

可以注意到，即使在上面区分动态类型与静态类型的例子中，我也没有写下面这种代码：

```c
int a = 1;
a = TRUE;
```

这是一段 C 语言代码，并且它是正确且能够通过编译的。很多人认为一门语言在变量定义时需要声明类型（比如这里的`int`）就认为它是”强类型“的，这实际上属于完全的误解——甚至 C 语言还是静态弱类型的。判断一个变量是什么类型的，实际上根本不需要依赖于程序员显式声明类型：

```
a = 1
b = true
c = []
```

在上面这段代码中，程序员并没有为这三个变量声明类型，但编译期仍旧能够很容易地得知 a 是数字、b 是布尔量、而 c 是一个列表/数组。这种无需显式声明类型也能推导出变量类型的能力被称为”类型推断“。因此，在很多现代的静态类型编程语言中，都是可以在许多情况中使用编程语言的类型推断能力，而无需操心为变量给出一个具体的声明的：

```c++
auto h{new Holder{42}}; // Holder<int> *
auto num{42} // int
auto nums{new int[10]}; // int *
auto nums2{std::array<int, 5>{1, 2, 3, 4, 5}}; // std::array<int, 5>
std::array<int, 5> nums3{1, 2, 3, 4, 5}; // std::array<int, 5>
```

静态类型语言一个很大的优势在于，能够通过类型系统在编译阶段检查出程序中一些潜在的 BUG，例如考虑下面这段 Python 代码：

```python
def get_text_length(s):
    return len(s)

get_text_length(42)
```

这段代码只有在实际运行到了`get_text_length(42)`这一句时才会报错。而在一些较大的项目中，有些代码可能本就很难被运行到，若类似这样的代码潜藏在程序中，就会产生许多难以发现的 BUG。而在一些静态类型语言，比如 TypeScript 中，这样的问题将在编译时被检查出来：

```typescript
function getTextLength(s: string) {
  return len(s);
}

getTextLength(42);
```

在编译时，`getTextLength(42)`会直接报错，因为 TypeScript 知道`getTextLength`函数只能用于字符串。类似这样的被称作”静态类型检查“的工作提升了代码的可靠性。

再考虑下面这段 Python 代码，思考静态类型带来的另一个优势：

```python
def process_string(s):
    s.split(...)
    ...

process_string(...)
```

在你编写`process_string`函数时，你会发现当你输入了`s.`之后，编辑器并没有像你期望地给出提示，告诉你变量`s`上可以调用哪些方法，比如`split`、`join`、`isnumeric`等——因为 Python 不知道变量`s`是什么类型的，不知道它是字符串、数字、布尔量或是其他什么，因此自然不会给你这些提示。

而在 TypeScript 中，你标注了`s`的类型之后，编辑器就能根据类型给出相应的提示：

```typescript
function processString(s: string) {
  s.split(...)
  ...
}

processString(...)
```

在这里，当你输入了`s.`之后，编辑器知道变量`s`是一个字符串，因此就会给出相应的提示。

这就是静态类型的另一大优势：可以在编写代码时给出更多的提示。并且，结合之前提到的”类型推断“，实际上在很多现代的静态类型语言中，你都不怎么需要手动标注变量的类型——最常见的只是你需要标注函数中参数的类型而已。因此，对于很多程序员来说，静态类型语言反而意味着只要付出极少的代价（添上一点点类型标注）就可以获得极高的编程效率提升（得益于编辑器提供的智能提示和静态类型检查）。

而在过去，在编辑器和编译器还没有今天这么智能的时代，静态类型语言既没有类型推断，而编辑器也没有智能提示，人们普遍认为静态类型语言的开发效率要比动态类型语言更低。然而在今天，事情已经完全不一样了。

不过，动态类型语言也并非完全无法享受类型推断与智能提示带来的好处。例如 Python 自 3.5 后提供了被称作”类型提示（type hints）“的语法，你也可以通过在变量后面加个冒号，标上可选的类型，提示编辑器该变量的类型，以获得智能提示，就像 TypeScript 一样。很多动态类型编程语言都采用了这种方式，这被称为”渐进式类型“，即并不强制标上类型，而是在你认为需要的地方标上类型。只不过，相比大多数静态类型语言，大多数动态类型语言中的”渐进式类型“不够完备，缺少足够强大的类型推断能力。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gaoge011022.gitbook.io/missing-necessary-knowledge-for-cs-students/ji-chu-zhi-shi/bian-cheng-yu-yan/statically-typed-and-dynamically-typed.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
