Skip to content

DAY3 ​

1.数据类型转换 ​

  1. 自动类型转换(隐式) 对两种数据进行运算,往往先是小的类型->大的类型,之后再进行运算(bool < int < float < complex)
    注=>print(None == False) 此时结果为False,并不会自动转换(None 不参与数值类型的自动提升)
    =>两个整数相除是浮点型 1.0/1=1.0 * (这里体现了健壮性,即考虑所有场景) *
    =>整型和字符串型不能直接运算 (因为无法自动转换)
  2. 强制类型转换
    int(x [,base]) 将x转换成一个整数,base用来指定字符串是几进制
       print(int("1111", base=2))   # 15
    float(x),str(),bin(),oct(),hex().......

补充整理:原稿「两个整数出发是浮点型」应为「两整数相除」;「整形」应为「整型」。

自动提升的顺序记忆:bool → int → float → complex。 一个容易踩的坑:True + True == 2(bool 是 int 的子类), 但 None + 1 会直接 TypeError —— None 不参与这套提升。

另外 int("3.14") 会报错,字符串转数字时必须保证字符串本身是合法整数格式; 要转小数用 float("3.14")。不确定用户输入长什么样时,一律配 try/except。

2.字符的编码和解码 ​

因为计算机只能读懂二进制,所以只能将其转换成二进制
编码:将字符串转换成二进制(中文gbk)
解码:将二进制转换成字符串
utf-8:万国码

手动进行编码解码 ​

python
b = myStr.encode("utf-8")     # 编码:str  -> bytes
s = b.decode("utf-8")         # 解码:bytes -> str

补充整理:原稿写成 myStr.decode(...),这是错的—— str 对象没有 decode 方法,只有 bytes 才有。 记住方向:编码用 str.encode(),解码用 bytes.decode()。

另外补充几点:

  • Python 3 里 str 是 Unicode 文本,bytes 是字节序列,两者不能混用
  • 读写文件要显式指定编码:open("a.txt", encoding="utf-8"), 不写的话用的是系统默认编码,换台机器就可能乱码
  • 网络传输、存盘都是字节;打印、处理是字符串,边界处一定要显式转换
  • 原稿提到的 txt 乱码问题,根因就是写用 gbk、读用 utf-8, 两边对不上必然报错或乱码。统一用 UTF-8 是唯一的省心做法

3.输入和输出 ​

1.输入(让用户与程序交互)

python
name = input("请输入")   # 键盘输入默认就是字符串类型

2.输出(展示程序中的内容,展示在控制台,一般用于代码调试以及测试) 普通输出,格式化输出
其中格式化输出包括:字符串中使用占位符%,字符串的 .format() 方法, 数字格式化(配合 .format()), 使用大括号来转义大括号, f-string(格式化字符串字面量)

补充整理:三种格式化方式,现代 Python 只用 f-string:

python
name, score = "路中麋鹿", 95.5

f"{name} 考了 {score} 分"          # 推荐:简洁直观,还能直接写表达式
"{} 考了 {} 分".format(name, score) # 老式,兼容性好
"%s 考了 %.1f 分" % (name, score)   # 最老,基本只在维护旧代码时见到

f"{score:>6.1f}"   # 右对齐、宽 6、保留 1 位小数

input() 返回的一定是字符串,做数值运算前必须转: age = int(input("年龄:"))——不转会得到 "18" + 1 的 TypeError。

4.运算符 ​

  1. 算数运算符
    +、-、*、/、//、%、**
  2. 赋值运算符
    =、+=、-=、*=、/=、//=、%=、**=

:= 海象运算符(在表达式中同时进行赋值和返回赋值) ​

在条件判断的时候同时赋值

python
if (n := len(data)) > 10:
    print(f"数据有 {n} 条,太多了")

补充整理:海象运算符的价值是避免重复计算。 上面这段如果不用它,要么 len(data) 算两次,要么先单独一行赋值。 常用于 while (line := f.readline()): 这类循环读取场景。

  1. 比较运算符
    ==、!=、>、<、>=、<=
    **不同类型的数据无法比较
  2. 逻辑运算符
    and、or、not
    其中 and 和 or 都是短路求值——左边能定结果就不再算右边,提高执行效率
    python
    False and expensive_call()   # 右边不会执行
    True  or  expensive_call()   # 右边不会执行
  3. 成员运算符
    in、not in
    in 判断元素是否在序列/容器中找到,找到返回 True
    not in 判断是否不包含在容器中
  4. 身份运算符
    is、is not
    is 判断两个标识符是不是引用同一个对象
    is not 判断是否不是同一个对象

补充整理:原稿「短路与和短路或」表述不准,Python 里叫短路求值(short-circuit)。

== 和 is 的区别是面试高频题,务必分清:

比较比的是什么示例
==值是否相等1000 == 1000 → True
is是否是同一个对象(内存地址)1000 is 1000 → 可能为 False

判断 None 必须用 is:if x is None:(用 == 可能触发自定义 __eq__)。 小整数(-5 ~ 256)Python 做了缓存池,所以 a is b 对小整数常为 True, 但这只是实现细节,不要依赖它。

浅拷贝与深拷贝 ​

补充整理:原稿只留了「浅拷贝:」「深拷贝:」两个空标题,这里补上。

python
import copy

a = [1, [2, 3]]

b = a              # 赋值:只是多一个名字,指向同一个对象
c = a.copy()       # 浅拷贝:外层是新列表,内层子对象仍共享
d = copy.deepcopy(a)  # 深拷贝:内外全都是新的

a[1].append(4)
print(b[1])   # [2, 3, 4]  ← b 和 a 本就是同一个对象
print(c[1])   # [2, 3, 4]  ← 浅拷贝的内层仍被改到!这是最容易踩的坑
print(d[1])   # [2, 3]     ← 深拷贝完全不受影响

三种方式一句话区分:

方式外层容器内部嵌套对象用途
赋值 =共享共享只是起别名
浅拷贝 list() / copy() / [:]新建共享只有一层的数据够用
深拷贝 copy.deepcopy()新建新建嵌套结构要完全独立时

实践:处理嵌套的 dict/list(比如接口返回的 JSON)时, 想要改了不影响原数据,就得用 deepcopy。

  1. 运算符优先级

优先级越高越先执行,同优先级从左往右运算(指数**特殊:从右往左运算)

  1. **(指数运算):优先级最高,用来做幂次方计算
  2. ~、+、-(单目运算符):~按位取反;+一元正号、-一元负号,仅对单个数字生效
  3. *、/、%、//:乘法、除法、取模(求余数)、地板除(取整除)
  4. +、-(双目运算符):普通加法、减法
  5. >>、<<:二进制右移、二进制左移
  6. &:按位与运算
  7. ^、|:按位异或、按位或运算
  8. <=、<、>、>=:大小比较运算符
  9. ==、!=:相等判断运算符

补充整理:原稿写的 <> 需要修正——它在 Python 2 里是不等于的写法, 在 Python 3 中已被彻底移除,写出来会直接报 SyntaxError。 Python 3 里不等于只有一种写法:!=。

  1. =、%=、/=、//=、-=、+=、*=、**=:各类复合赋值运算符,用来给变量赋值、自更新数值
  2. is、is not:身份运算符,判断两个对象是否为同一个内存对象
  3. in、not in:成员运算符,判断元素是否属于容器内部
  4. not、and、or(逻辑运算符):优先级最低;优先级顺序not > and > or

补充关键细节 ​

  • 括号()优先级高于所有运算符,可通过括号强制调整运算顺序;
  • 指数**是右结合:2**3**2等价于2**(3**2),不是(2**3)**2;
  • 单目正负(如-3)优先级高于乘除;普通加减是双目,优先级低于乘除。

5.python编码规范 ​

  1. 缩进:代码块不要同时混用 tab 和空格
  2. 同一行显示多条语句,有时候可以用 ; 来分隔有时候不行,所以一般一条语句一行
  3. 不能以空格来结束一行代码

补充整理:原稿「就只用 tab 就好」这条建议需要纠正—— 官方的 PEP 8 规范明确推荐用 4 个空格缩进,不推荐用 tab。 理由是同一个 tab 在不同编辑器里显示的宽度可能不同(4 或 8), 混用 tab 和空格在 Python 3 里更是会直接触发 TabError。

正确做法:

  • 缩进统一用 4 个空格(主流编辑器都能设置「tab 自动转空格」)
  • 一个项目里只选一种,不要混用
  • 现在的实践是直接用 ruff / black 自动格式化,不用手工纠结

其余 PEP 8 要点:运算符两侧加空格(a = b + c)、 逗号后加空格、行长度不超过 79(实际项目多放宽到 88~120)、 变量名用 snake_case、常量用 UPPER_CASE。

第四章 流程控制语句 ​

一、分支结构核心作用 ​

根据条件表达式的布尔结果(True/False),选择性执行对应代码块,实现程序分支走向,分为单分支、多分支、嵌套分支三类。

1. 单分支 if 语句 ​

基础语法 ​

if 条件表达式:
    条件成立时执行的代码块

执行逻辑 ​

  1. 计算条件表达式,得到布尔值;
  2. 若结果为True,执行缩进内的代码;
  3. 若结果为False,直接跳过该段代码,向下顺序执行后续程序。

关键特点 ​

仅存在满足条件时的执行逻辑,无对应不满足条件的备用分支。


2. 多分支 if-elif-else 语句 ​

基础语法 ​

if 条件1:
    代码块1
elif 条件2:
    代码块2
elif 条件3:
    代码块3
# 可无限追加elif
else:
    所有条件均不满足时执行的代码块

执行逻辑 ​

  1. 自上而下依次校验每一个条件;
  2. 一旦某一条条件判定为True,执行对应代码块后,直接跳出整个多分支结构,不再校验剩余条件;
  3. 全部if/elif条件均不成立时,执行else内代码;else为可选部分,可省略。

关键特点 ​

多区间、多场景判断专用,多个分支互斥,同一时刻只会执行其中一段代码。


3. 嵌套分支 ​

概念 ​

在if/elif/else任意一个分支的代码块内部,再次完整书写if分支结构,形成多层条件校验。

基础语法模板 ​

if 外层条件:
    # 外层分支内部嵌套内层if结构
    if 内层条件:
        内层成立代码
    else:
        内层不成立代码
else:
    外层条件不成立代码

执行逻辑 ​

先完成外层条件判断,只有外层条件成立、进入对应代码块后,才会执行内层分支的条件校验;层级从上至下逐层判断。

关键特点 ​

用于存在递进、分层关系的复合条件;依靠缩进区分内外层代码块,层级不宜过多,否则降低代码可读性。

通用注意事项 ​

  1. Python使用缩进划分分支代码块,同一分支内代码缩进空格数必须统一;
  2. 所有分支的条件表达式最终都只会产出布尔值True或False;
  3. 分支结构执行完毕后,统一继续运行分支后方的代码。

第四章 流程控制语句(分支结构笔记 补充) ​

一、三目运算符(三元表达式) ​

语法格式 ​

变量 = 条件成立结果 if 条件表达式 else 条件不成立结果

执行逻辑 ​

  1. 先判断中间的条件表达式;
  2. 条件为True,取if左侧的值;
  3. 条件为False,取else右侧的值;
  4. 整体表达式最终返回一个结果,可直接赋值给变量。

核心特点 ​

  1. 简化双分支if-else,将多行分支压缩为单行代码;
  2. 仅适用于二选一简单逻辑,不适合复杂多分支场景。

二、match-case 模式匹配(Python3.10+) ​

基础语法格式 ​

match 待匹配变量:
    case 匹配值1:
        匹配成功执行代码块
    case 匹配值2:
        匹配成功执行代码块
    case _:
        所有匹配均失败时执行(兜底分支,等价于else)

执行逻辑 ​

  1. 使用match关键字绑定需要匹配的目标数据;
  2. 从上至下依次比对每一条case的值;
  3. 匹配成功则执行对应代码块,执行完成后直接跳出整个match结构;
  4. 全部case匹配失败,会执行case _兜底分支,case _可选。

拓展功能 ​

  1. 可匹配常量、数据结构(列表、元组、字典);
  2. 支持多条件或匹配、值绑定、类型匹配;