Python 学习笔记

Python 学习笔记


第 1 章 Python 入门与基础

1.1 Python 简介

  • 发明者:吉多・范罗苏姆(龟叔),1989 年发明,1991 年发布
  • 特点:简洁易读、开源、跨平台、胶水语言,支持面向对象 / 过程 / 函数式编程
  • 应用:AI、Web 开发、自动化、数据分析、爬虫、游戏、桌面软件
  • 版本:Python3 为主流,不兼容 Python2

1.2 环境与开发工具

  • 运行环境:安装 Python 时勾选Add Python to PATH

  • 开发工具(IDE):

    • PyCharm:功能全,适合专业开发,内存占用高
    • VSCode:轻量免费,需装 Python 插件
    • IDLE:Python 自带,适合新手
  • 虚拟环境:隔离项目依赖,避免版本冲突,实操命令:

    # 创建虚拟环境(Python3.6+)
    python -m venv myenv  # Windows/Linux/Mac通用
    # 激活虚拟环境
    # Windows(cmd):myenv\Scripts\activate.bat
    # Windows(PowerShell):myenv\Scripts\Activate.ps1
    # Linux/Mac:source myenv/bin/activate
    # 退出虚拟环境
    deactivate
    

1.3 基础语法

  • 缩进:强制用 4 个空格缩进,不用大括号 {}

  • 注释:单行 #,多行 '''"""

  • 大小写敏感,符号全为英文符号

  • 交互模式:输入 python 进入,quit() 退出

  • ⚠️ 常见语法坑:

    • 混淆 =(赋值)和 ==(比较)
    • 缩进不一致导致 IndentationError
    • 中文符号(如中文逗号、括号)触发 SyntaxError

第 2 章 编程核心概念

2.1 对象与引用

  • 一切皆对象:Python 中所有东西都是对象,但变量不是对象,是指向对象的引用

  • 对象组成:标识(id,内存地址)、类型(type)、值(value)

  • 引用:变量存储对象地址,指向堆内存中的对象

  • 不可变对象:int、str、tuple、bool,修改则创建新对象

    • 哈希性:可哈希(hashable),可作为字典的键、集合的元素(哈希表底层依赖哈希值)

    可变对象:list、dict、set,可直接修改原对象

    • 哈希性:不可哈希(unhashable),不能作为字典的键、集合的元素(修改后哈希值会变,破坏哈希表结构)
  • ⚠️ 元组特殊点:元组本身不可变,但内部可变子对象(如列表)可修改:

    t = (1, [2,3])
    t[1].append(4)  # 执行后 t = (1, [2,3,4])
    
  • 哈希性核心规则:

    • 可哈希对象:必须满足「不可变 + 有 __hash__ 方法」,如 int/str/tuple(无可变子对象)

    • 不可哈希对象:可变对象(list/dict/set)或重写了 __hash__ 为 None 的对象

      # 可哈希(合法)
      d1 = {1: "数字", "name": "字符串", (1,2): "元组"}  
      s1 = {1, "a", (1,2)}
      
      # 不可哈希(报错 TypeError: unhashable type)
      d2 = {[1,2]: "列表"}  # 列表不可哈希
      s2 = {{1:2}: "字典"}  # 字典不可哈希
      

2.2 标识符与变量

  • 命名规则:字母 / 下划线开头,区分大小写,不能用关键字
  • 命名规范:
    • 类名:大驼峰(Student、MyClass)
    • 变量 / 函数 / 模块:小写 + 下划线(name、say_hello)
    • 常量:全大写(MAX_SPEED)
  • 变量赋值:动态类型,无需声明类型,a = 10

2.3 数据类型

2.3.1 基本类型

  • int:整数,无大小限制,支持二进制 / 八进制 / 十六进制
  • float:浮点数,科学计数法表示
  • bool:True(1)、False(0)
  • str:字符串,不可变,Unicode 编码

2.3.2 序列类型

  • list:列表,可变有序序列,[1,2,3]
  • tuple:元组,不可变有序序列,(1,2,3)
  • dict:字典,无序键值对,键必须不可变,{"name":"张三"}
  • set:集合,无序无重复元素,基于字典实现,{1,2,3}

2.4 运算符

  • 算术:+ - * / // % **

  • 比较:> < >= <= == !=,可连用(3<a<10

  • 身份:is/is not(比较地址),==(比较值)

  • 成员:in/not in(判断是否在序列中)

  • 逻辑:and or not

  • 位运算:& | ^ ~ << >>

    概念 区别 示例
    is vs == is 比较内存地址,== 比较值 a=10;b=10 → a is b (True);a=[1];b=[1] → a is b (False)
    isinstance VS type type不推荐,无法识别子类 isinstance(10, int)(推荐); type(10) == int(不推荐,无法识别子类)

第 3 章 字符串

3.1 定义与特点

  • 单 / 双 / 三引号创建,三引号支持多行
  • 不可变对象,不能直接修改原字符串
  • 转义字符:\n 换行、\t 制表符、\\ 反斜杠

3.2 常用操作

  • 索引 / 切片:s[0]s[1:5]s[::-1](反转)
  • 拼接:+(新建对象)、join()(高效)
  • 替换:replace()(生成新字符串)
  • 分割 / 合并:split()join()
  • 查找:find()count()startswith()endswith()
  • 大小写:upper()lower()title()
  • 去空格:strip()lstrip()rstrip()
  • 格式化:format()、f-string(f"{name}{age}"
  • 可指定删除字符: strip()

3.3 可变字符串

  • io.StringIO 实现原地修改字符串

3.4 正则表达式

3.4.1 核心概念

  • 作用:匹配、查找、替换、分割字符串
  • 模块:re

3.4.2 常用函数

  • match:从头匹配,成功返回对象
  • search:全局搜索第一个匹配项
  • findall:返回所有匹配结果列表
  • sub/subn:替换字符串
  • split:分割字符串

3.4.3 匹配规则

  • 字符:.任意字符、\d数字、\w字母数字下划线、\s空白
  • 限定符:*0+、+1+、?0/1、{m,n}指定次数
  • 边界:^开头、$结尾、\b单词边界
  • 分组:()分组,\num引用分组,(?P<name>)命名分组
  • 原生字符串:r"",解决转义冲突

第 4 章 序列(列表、元组、字典、集合)

4.1 列表 list

  • 创建:[]list()range()、推导式

  • 增:append()(尾部)、extend()insert()

  • 删:delpop()(删指定索引)、remove()(删指定值)

  • 查:索引、index()count()、切片

  • 改:直接赋值 lst[0] = 10

  • 排序:sort()(原地)、sorted()(新列表)、reverse()

    概念 区别 示例
    sort() vs sorted() sort() 原地排序(无返回),sorted() 返回新列表 lst=[3,1,2]; lst.sort() → lst=[1,2,3];sorted(lst) → 新列表,原 lst 不变
    append()vsextend() lst=[1,2]; lst.append([3,4]) → [1,2,[3,4]]lst.extend([3,4]) → [1,2,3,4]
    delvspop()vsremove() del 按索引删(无返回)、pop() 按索引删(有返回)、remove() 按值删(无返回)

4.2 元组 tuple

  • 不可变列表,无增删改方法
  • 创建:()tuple(),单元素必须加逗号 (1,)
  • 适用:固定数据、函数返回值、字典键

4.3 字典 dict

  • 键值对存储,键唯一且不可变
  • 创建:{}dict()zip()
  • 增改:d[key] = valueupdate()
  • 删:delpop()clear()
  • 查:d[key]get()(安全)、keys()values()items()
  • 底层:哈希表(散列表),空间换时间,查询极快

4.4 集合 set

  • 无序、无重复元素,自动去重
  • 操作:交集&、并集|、差集-
  • 增:add()、删:remove()

第 5 章 控制语句

5.1 选择结构

  • 单分支:if 条件:
  • 双分支:if-else
  • 多分支:if-elif-else
  • 三元运算符:值1 if 条件 else 值2
  • 条件为 False:0、0.0、None、空序列、空字典

5.2 循环结构

  • while:while 条件:,适合未知次数循环
  • for:遍历可迭代对象,for 变量 in 可迭代对象:
  • range:range(start,end,step),生成整数序列
  • break:结束整个循环;continue:结束本次循环
  • else:循环正常结束(未被 break)时执行

5.3 推导式

  • 列表:[x for x in range(10) if x%2==0] # 运行结果:[0,2,4,6,8]
  • 字典:{k:v for k,v in zip(list1,list2)}
  • 集合:{x for x in range(10)}
  • 生成器:(x for x in range(10)),一次性迭代

第 6 章 函数

6.1 定义与调用

  • 语法:def 函数名(参数):,函数是对象
  • 作用:代码复用、模块化
  • 返回值:return 结束函数并返回值,无 return 返回 None

6.2 参数类型

  • 位置参数:按顺序传递
  • 默认参数:def func(a,b=10),必选参数在前
  • 可变参数:
    • *args:接收多个位置参数,打包成元组
    • **kwargs:接收多个关键字参数,打包成字典
  • 命名参数:调用时指定参数名 func(b=20,a=10)
  • 强制命名参数:可变参数后的参数必须命名

6.3 作用域

  • 局部变量:函数内,访问快,优先级高
  • 全局变量:函数外,需用 global 声明修改
  • nonlocal:嵌套函数中声明外层局部变量

6.4 高级特性

  • lambda 匿名函数:lambda a,b:a+b,简洁单行函数
  • eval:执行字符串表达式,慎用(安全风险)
  • 递归:自己调用自己,必须有终止条件
  • 嵌套函数:函数内定义函数,封装数据
  • LEGB 规则:局部→嵌套→全局→内建
    • 「Local(函数内)→ Enclosing(嵌套函数外层)→ Global(模块级)→ Built-in(Python 内置),按这个顺序找变量,找到即停」;

6.5 参数传递

  • 引用传递:全是对象引用
  • 可变对象:函数内修改影响原对象
  • 不可变对象:函数内修改创建新对象,不影响原对象
  • 浅拷贝:拷贝对象,不拷贝子对象
  • 深拷贝:copy.deepcopy(),递归拷贝所有子对象
  • ✅ 核心结论:
    • 赋值 a = b:只是贴标签,共用一个对象
    • 浅拷贝 copy():只拷贝第一层
    • 深拷贝 deepcopy():完全独立,递归拷贝所有子对象
    • 不可变对象(str/int/tuple)怎么拷贝都一样
    • 可变对象(list/dict)必须用深拷贝才安全(列表套列表、字典套列表必用)
  • ⚠️ 全局变量修改:函数内部只能读全局变量,修改必须加 global;嵌套函数改外层变量用 nonlocal
  • 闭包:内部函数 + 引用外部环境变量 → 可保存状态(装饰器基础)

6.6 常用内置函数

函数名 用途 示例
len() 计算长度 len([1,2,3]) → 3
enumerate() 遍历带索引 for idx, val in enumerate(["a","b"]): print(idx, val)
zip() 多序列打包 list(zip([1,2], ["a","b"])) → [(1,"a"), (2,"b")]
sorted() 通用排序 sorted({"b":2, "a":1}.items(), key=lambda x:x[0]) → [("a",1), ("b",2)]
map() 批量处理 list(map(lambda x:x*2, [1,2])) → [2,4]
filter() 过滤元素 list(filter(lambda x:x>0, [-1,0,1])) → [1]

第 7 章 面向对象(OOP)

7.1 核心思想

  • 面向过程:执行者思维,步骤化,适合简单问题
  • 面向对象:设计者思维,封装数据与行为,适合复杂协作
  • 三大特征:封装、继承、多态

7.2 类与对象

  • 类:模板,class 类名:
  • 对象:类的实例,对象 = 类名()
  • 组成:属性(数据)、方法(行为)

7.3 构造与初始化

  • __init__:初始化方法,初始化对象,第一个参数 self
  • __new__:创建对象,系统自动调用
  • self:代表当前实例对象,必须为第一个参数
  • ⚠️ 核心区别:__init__ 不是构造函数,__new__ 才是(__new__ 创建对象,__init__ 初始化属性)

7.4 属性与方法

  • 实例属性:self.属性,属于对象,互不共享

  • 类属性:类名.属性,所有对象共享

  • ⚠️ 类属性坑:类变量不要用可变对象(如列表),否则所有实例共享导致数据污染:

    class A:
        lst = []  # 危险!所有实例共享该列表
    
  • 实例方法:def 方法(self),调用:对象.方法()

  • 类方法:@classmethod,第一个参数 cls,调用:类名.方法()

  • 静态方法:@staticmethod,无默认参数,调用:类名.方法()

7.5 封装

  • 私有成员:双下划线开头 __属性/__方法,约定私有
  • 外部访问:对象._类名__私有成员(非严格私有)
  • ⚠️ Python 无真正私有,仅靠约定
  • @property:将方法转为属性调用,实现 getter/setter

7.6 继承

  • 语法:class 子类(父类)
  • 作用:代码复用,扩展父类功能
  • 方法重写:子类重新定义父类方法
  • 调用父类:super().方法()父类名.方法(self)
  • 多重继承:支持多父类,MRO 从左到右查找方法(用 类名.mro() 查看顺序,不要猜)
    • 「方法解析顺序,解决多继承时的方法查找冲突,比如 class A (B,C): … 用 A.mro () 看查找顺序,不要凭直觉」
  • 根类:object,所有类默认继承

7.7 多态

  • 同一方法,不同对象表现不同行为
  • 条件:继承、方法重写
  • 特点:方法多态,属性无多态

7.8 特殊方法

  • __str__:打印对象时调用,自定义输出
  • __del__:析构方法,对象销毁时调用
  • __call__:让对象可像函数一样调用
  • 运算符重载:__add__(+)、__len__(len) 等

7.9 设计模式(极简示例列举)

  • 工厂模式:统一创建对象,解耦创建与调用
  • 单例模式:一个类仅一个实例,重写 __new__ 实现
  • 简单工厂模式:通过函数统一创建不同子类实例
  • 适配器模式:适配不同接口,让不兼容的接口可协同工作

第 8 章 模块与包

8.1 模块

  • 一个 .py 文件就是一个模块

  • 作用:分类存放代码、避免重名、方便复用

  • 导入方式:

    import 模块名
    from 模块名 import 函数/类
    from 模块名 import *
    

8.2 包(Package)

  • 包含 __init__.py 的文件夹就是包

  • 作用:管理多个模块

  • 导入:from 包名 import 模块名


第 9 章 异常机制

9.1 异常是什么

程序出错时会抛出异常,不处理就崩溃。

9.2 异常处理结构

try:
    可能出错的代码
except 异常类型:
    出错后执行
else:
    不出错才执行
finally:
    无论如何都执行

9.3 常见异常

  • SyntaxError 语法错误
  • IndexError 索引越界
  • KeyError 字典键不存在
  • AttributeError 属性不存在
  • ZeroDivisionError 除 0
  • FileNotFoundError 文件不存在

9.4 主动抛异常

# 异常链(Python3.11+ 新特性)
try:
    1/0
except ZeroDivisionError as e:
    raise ValueError("数值错误") from e  # 保留原异常栈

9.5 自定义异常

class MyError(Exception):
    pass

raise MyError("自定义异常信息")

9.6 实战最佳实践

import logging
# 配置日志
logging.basicConfig(level=logging.ERROR, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")

try:
    1/0
except ZeroDivisionError as e:
    # 记录异常(包含堆栈信息)
    logging.exception("除零错误发生")
finally:
    # 释放资源(文件、锁、网络连接等)
    print("资源已释放")
  • ⚠️ 注意事项:

    • 不要裸 except:(会捕获 KeyboardInterrupt,导致程序无法终止)
    • 异常捕获尽量精确,避免随便捕获 Exception

第 10 章 装饰器

10.1 作用

在不修改原函数代码的前提下,给函数增加功能。

10.2 本质

把函数当作参数,返回一个新函数。

10.3 基础写法

def 装饰器(func):
    def wrapper():
        # 执行前逻辑
        func()
        # 执行后逻辑
    return wrapper

@装饰器
def f():
    pass

10.4 带参数、带返回值

def deco(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return wrapper

10.5 标准万能装饰器

import functools

def 装饰器(func):
    @functools.wraps(func)  # 保留原函数__name__/__doc__,必加!
    def wrapper(*args, **kwargs):
        # 执行前逻辑(如日志、计时、权限校验)
        res = func(*args, **kwargs)
        # 执行后逻辑
        return res
    return wrapper

# 示例:带参数的装饰器
def deco_with_param(param):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            print(f"装饰器参数:{param}")
            res = func(*args, **kwargs)
            return res
        return wrapper
    return decorator

@deco_with_param("test")
def demo():
    print("原函数执行")

demo()  # 运行结果:装饰器参数:test → 原函数执行

10.6 装饰器叠加执行顺序

def deco1(func):
    def wrapper():
        print("deco1 前")
        func()
        print("deco1 后")
    return wrapper

def deco2(func):
    def wrapper():
        print("deco2 前")
        func()
        print("deco2 后")
    return wrapper

@deco1
@deco2
def f():
    print("原函数")

f()  # 运行结果:deco1 前 → deco2 前 → 原函数 → deco2 后 → deco1 后
  • 核心规则:@装饰器 1 在上、@装饰器 2 在下 → 执行顺序:装饰器 1 外层 → 装饰器 2 外层 → 原函数 → 装饰器 2 内层 → 装饰器 1 内层

10.7 带缓存的装饰器

# 带缓存的装饰器
from functools import lru_cache

@lru_cache(maxsize=128)  # 缓存函数返回值,避免重复计算
def fib(n):
    if n <= 2:
        return 1
    return fib(n-1) + fib(n-2)

10.8 常用场景

  • 日志记录
  • 函数计时
  • 权限检查
  • 参数校验

第 11 章 生成器 & 迭代器

11.1 迭代器(Iterator)

  • 可以被 for 遍历的对象
  • 拥有 __iter____next__ 方法

11.2 生成器(Generator)

一边循环一边计算,不占大量内存,迭代器的一种。

  • 两种写法:

    # 1. 推导式
    g = (x for x in range(10))  # 运行结果:生成器对象,仅迭代一次
    
    # 2. yield 函数
    def gen():
        yield 1
        yield 2
    
    g = gen()
    print(next(g))  # 1
    print(next(g))  # 2
    
  • 核心特点:

    • 惰性计算,仅在迭代时生成数据
    • 只能遍历一次,用完即空
    • 适合大数据、大文件、无限序列场景

第 12 章 并发编程(线程、进程、协程)

12.1 线程

  • 最小执行单位
  • 共享进程资源
  • 模块:threading
  • 适用场景:IO 多路并发
# 线程示例(IO 密集):

import threading
import time

def download(url):
    print(f"开始下载{url}")
    time.sleep(2)  # 模拟IO等待
    print(f"完成下载{url}")

# 启动多线程
urls = ["url1", "url2", "url3"]
threads = []
for url in urls:
    t = threading.Thread(target=download, args=(url,))
    threads.append(t)
    t.start()
# 等待所有线程完成
for t in threads:
    t.join()
print("所有下载完成")
# 线程池(简化多线程代码)
from concurrent.futures import ThreadPoolExecutor
import time

def download(url):
    time.sleep(2)
    return f"{url} 下载完成"

with ThreadPoolExecutor(max_workers=3) as pool:
    urls = ["url1", "url2", "url3"]
    results = pool.map(download, urls)
    for res in results:
        print(res)

12.2 进程

  • 独立内存空间
  • 适合 CPU 密集型任务(计算、压缩、加密)
  • 模块:multiprocessing

12.3 协程

  • 极轻量,用户态切换
  • 适合 I/O 密集型任务(网络、文件、爬虫)
  • 模块:asyncio
# 协程示例(IO 密集):

import asyncio

async def download(url):
    print(f"开始下载{url}")
    await asyncio.sleep(2)  # 模拟IO等待
    print(f"完成下载{url}")

# 运行协程
async def main():
    urls = ["url1", "url2", "url3"]
    tasks = [download(url) for url in urls]
    await asyncio.gather(*tasks)

asyncio.run(main())
print("所有下载完成")

12.4 选型建议

  • IO 密集(网络、文件、爬虫)→ 协程 asyncio
  • IO 多路并发 → 线程
  • CPU 密集(计算、压缩、加密)→ 进程

第 13 章 网络编程

13.1 核心基础

  • 基于 TCP/IP 模型
  • Socket 套接字:服务端(绑定 → 监听 → 接收)、客户端(连接 → 发送 / 接收)

13.2 常用模块

  • socket(原生,仅用于学习)
  • requests(HTTP 请求,实战首选)
  • FastAPI/Flask(网络服务开发,实战首选)

第 14 章 文件操作

14.1 打开文件

f = open("a.txt", "r", encoding="utf-8")  # ⚠️必须指定 encoding="utf-8"
  • 模式:r 读、w 写(覆盖)、a 追加、rb 二进制

14.2 自动关闭

with open("xxx.txt", "r", encoding="utf-8") as f:
    data = f.read()
  • 优势:自动关闭文件,即使报错也不泄露文件句柄

14.3 读写方法

  • read():读取全部内容(小文件)
  • readline():逐行读取
  • readlines():读取所有行到列表
  • write():写入内容

14.4 示例

大文件读取:

# 逐行读取,不加载整个文件到内存
with open("big_file.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

批量读取文件夹下所有 txt 文件:

import os
from pathlib import Path

folder = Path("./data")
if not folder.exists():
    folder.mkdir(parents=True)  # 递归创建文件夹
for file in folder.glob("*.txt"):
    with open(file, "r", encoding="utf-8") as f:
        content = f.read()
        print(f"文件{file.name}内容:{content[:50]}")  # 只打印前50字符

JSON / CSV 文件读写:

# 补充:JSON 文件读写
import json

# 写入
data = {"name": "张三", "age": 20}
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

# 读取
with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)

附录 : 常用内置模块速查

模块名 核心用途 高频函数 / 类
os 系统路径 / 文件操作 os.path.join()、os.mkdir()、os.path.exists()
sys 系统参数 / 环境 sys.argv、sys.path、sys.exit()
json JSON 解析 json.dumps()、json.loads()
time 时间处理 time.sleep()、time.time()、time.strftime()
datetime 日期时间 datetime.datetime.now()、strftime()、strptime()
logging 日志记录 logging.basicConfig()、logging.exception()
copy 拷贝对象 copy.copy ()(浅拷贝)、copy.deepcopy ()(深拷贝)
pathlib 路径处理(推荐) Path()、Path.joinpath()、Path.exists()

附录 :避坑清单

  1. 路径问题:不要写绝对路径(如 C:\xxx),用 pathlib/os.path 拼接路径
  2. 编码问题:打开文件必须指定 encoding="utf-8"
  3. 装饰器:必须加 @functools.wraps(func),否则原函数信息丢失
  4. 类属性:不要用可变对象(列表 / 字典)作为类变量
  5. 异常处理:不裸捕 except,不随便捕获 Exception
  6. 大文件:用逐行读取,避免加载整个文件到内存
  7. 拷贝:嵌套可变对象必须用深拷贝 copy.deepcopy()
  8. 生成器:生成器只能迭代一次,迭代后再次调用 next() 会抛 StopIteration
  9. 字符串拼接:大量拼接用 join() 而非 ++ 会频繁创建新对象,效率低)