🧩 第四章 面向对象编程技术:去除冗余、进行整理
📄 一句话概括

动态语言里类型嵌在运行时——注解存进 __annotations__ 但运行时不检查,传字符串照样返回 3。

📝 本节和前面几节的关系

4.10 收完三大要素,从这里开始讲语言是怎么把这些事做出来的。

一、类型写在哪

静态语言:类型写在代码里。int total = a + b;——不写就编译不过。 动态语言:类型嵌在运行时。total = a + b——类型信息在对象身上(type(obj))。 【嵌入】的意思就是:它本来就在,不需要你再声明一遍。

二、类型注解是什么

Python 从 3.5 起有了注解:def total(shapes: list) -> float: ...。 实测 total.__annotations__ 拿到 {'shapes': list, 'return': float}。 但传一个字符串进去,它照样返回 3。 注解只在开发和静态检查时起作用,运行时不管。

三、注解不是检查

它是给工具看的,不是给解释器看的。 mypy、IDE 的波浪线读的是它;Python 自己不看。 所以【写了注解】和【类型安全】是两件事——前者是文档,后者要工具兜。

四、代价

写起来省事,错起来晚:同一行代码,静态语言在编译期就拦住,动态语言可能跑到那一步才炸。 这不是缺陷,是取舍——省下的声明,用【晚发现】换的。 这正是 4.13 要说【退化】的前半句。

五、动手 Demo:通过嵌入类型使程序员的工作变轻松

给函数写上类型注解,看它被存到了哪里。 再传一个类型不对的参数,看运行时会怎样。

def total(shapes: list) -> float:
    return float(len(shapes))

print(total.__annotations__)
print(total("abc"))    # 类型不对,照样跑

实跑输出:

--------------------------------------------------------------------
通过嵌入类型使程序员的工作变轻松
--------------------------------------------------------------------

  动态语言里,**类型是【嵌】在运行时里的;**静态语言里,**类型是【写】在代码里的。**
  Python 从 3.5 起加了**类型注解**——可以不写,也能让工具替你查。

      def total(shapes: list) -> float: ...

  实测:注解会被存进 `__annotations__`,但**运行时不检查**。

      total.__annotations__ → {'shapes': <class 'list'>, 'return': <class 'float'>}
      传一个字符串进去会怎样:total("abc") → 3

  **注意第二行:传错了它照样跑,返回 3。**
  **注解只在开发和静态检查时起作用,运行时不管。**

                     静态类型(Java)     动态类型(Python)
  -----------------------------------------------------------
  类型写在哪         代码里               运行时(或注解)
  错类型何时发现     编译期               运行时(或工具)
  写起来             啰嗦                 省事

  **【嵌入类型】的意思是:**类型信息本来就嵌在对象里(`type(obj)`),
  **所以不需要你再声明一遍。**这也解释了为什么动态语言写起来快、错起来晚。

实测:注解被存进 __annotations__,但传字符串 "abc" 照样返回 3。 注解只在开发和静态检查时起作用,运行时不管——这是动态语言省事与错晚的同一枚硬币。

30 秒实验

  1. 给一个函数加上类型注解,再故意传错类型,看什么时候才炸。
  2. 打开 IDE 的静态检查,看它是不是能报出运行时不报的错。

常见误区

  1. 以为写了注解就有类型检查。解释器根本不看。
  2. 以为动态类型是没有类型。类型一直在,只是嵌在对象上。
自测三问(点开对答案) 1. 【嵌入类型】是什么意思? —— 类型信息本来就嵌在运行时对象里(type(obj)),所以不需要你再声明一遍。 2. 类型注解读了有用吗? —— 有用但不在运行时:它给静态检查工具和 IDE 看,解释器不检查,传错类型照样跑。 3. 动态类型的代价是什么? —— 写起来省事,错起来晚——静态语言编译期能拦的错,它可能跑到那一步才炸。

相关笔记