4040 字
11 分钟
Python笔记(自用)
2026-06-17

hhhhhhhhhhhh该笔记持续更新,仅更新自用部分,如有错误请在评论区指正,谢谢🙏

首次博客更新2025-12-29

类型注解#

  1. 给变量加类型注解
name: str = "Tom"
age: int = 18
price: float = 3.14
flag: bool = True

列表,字典:

nums: list[int] = [1, 2, 3]
names: list[str] = ["a", "b"]
info: dict[str, int] = {"Tom": 18}
  1. 返回值注解
def add(a: int, b: int) -> int:
return a + b
  1. Literal注解
from typing import Literal
status: Literal["success", "fail", "pending"]
  1. Optional注解
from typing import Optional
def get_name() -> Optional[str]:
return None
  1. Any
from typing import Any
data: Any = 123
data = "abc"
data = []
  1. Callable
Callable[[参数类型列表], 返回类型]

示例:

from typing import Callable
def apply(f: Callable[[int, int], int], a: int, b: int) -> int:
return f(a, b)

虚拟环境#

python -m venv .venv

基本语法#

input返回str类型

name = input("请输入你的名字:")
print("你好," + name)

类型转换

int("666")
print("知道了,你今年" + str(2) + "岁了!")

条件控制#

mood_index = int(input("Enter mood index: "))
if mood_index >= 60:
print("congratulation!")
elif 30 <mood_index < 60:
print("Nromal.")
else:
print("Sorry.")

布尔类型#

唯一实例#

唯一实例:TrueFalse 是 全局唯一的单例对象

a = True
b = True
print(a is b) # True
x = False
y = False
print(x is y) # True

不可变#

一旦创建,不能修改它的值:

a = True
# a[0] = False # ❌ TypeError

切片#

用法:序列[start : stop : step]

含义:从 start 开始,到 end 结束(不包含 end),步长为 step

step为负数(反向切片):

a = [0,1,2,3,4]
print(a[::-1])
[4,3,2,1,0]

列表#

shopping_list = ["apple", "banana", "cherry"]
shopping_list.append("orange")
print(shopping_list[0])
price = [100,200,301,129]
max_price = max(price)
min_price = min(price)
sorted_price = sorted(price)
print(max_price)
print(min_price)
print(sorted_price)
  • 方法:

对象.方法名(…)

  • 函数:

函数名.(对象)

列表的基操方法:

  • append()——末尾添加一个元素
  • extend()——添加多个元素( 参数必须是可迭代对象
  • insert(a,b)——指定位置插入
a = [1, 2, 3]
a.insert(1, 100)
print(a) # [1, 100, 2, 3]

插入会导致后续元素整体右移,效率较低

  • remove()——按值删除
  • pop()——按下标删除并返回( 不写参数默认删除最后一个: )
a = [1, 2, 3]
x = a.pop(1)
print(x) # 2
print(a) # [1, 3]
  • clear()——清空列表
  • reverse()—— 逆向输出
  • copy()—— 列表的拷贝
  • a.sort(reverse=True)—— (默认升序)列表排列

函数:

  • sorted(words, key=len, reverse=False)——返回新列表的排序
  • enumerate(可迭代对象, start=0)

示例:

lst = ['a', 'b', 'c']
for i, v in enumerate(lst):
print(i, v)

输出:

0 a
1 b
2 c

列表生成式#

  • [ 表达式 for 变量 in 可迭代对象 ]

map函数#

map(function, iterable)

把一个函数“批量作用”到可迭代对象的每个元素上,map返回的是迭代器

例:

nums = [1, 2, 3, 4]
res = map(lambda x: x * 2, nums)
print(list(res))

相当于

[x * 2 for x in nums]

元组#

在 Python 里,用逗号分隔的多个值会被自动打包成一个元组,即使没有外面的圆括号。

使用内置函数创建元组:tuple()

遍历输出元组元素:

print(len(t))
for i in range(len(t)):
print(i,t[i])

删除元组:del 元组名

字典#

contacts = {
("xioamin",23):"111111111",
("xiaohua",24):"222222222"
}
del contacts[("xioamin",23)]
contacts[("xiaomei",24)] = "123131"
print(contacts)
print(len(contacts))
  • 访问字典:
    1. 使用[]访问
student_grades = {
"语文": 90,
"数学": 95,
"英语": 88,
"科学": 92
}
# 访问 '数学' 键对应的值
math_score = student_grades["数学"]
print(math_score) # 输出: 95
2. 使用`.get(key, default=None)` 方法 (`default`为键不存在时返回的默认值)
  • items()方法:**无参数,**返回 返回字典中所有键值对组成的可迭代视图,每个元素是 (key, value) 元组 ,可以用 list() 转换成列表
  • 字典的遍历:拆开键和值
for k, v in d.items():
print(k, v)
  • pop() 用于 删除字典中的某个键,并返回对应的值
  • popitem()——随机删除
  • clear()——清空字典中所有元素
  • dict.update([other]) other:可选参数,可以是另一个字典、可迭代的键值对,或关键字参数。返回 None,原地修改调用字典。

字典生成式#

  • d={key:value for item in range}
  • d-{key:value for key,value in zip(lst1,lst2)}

集合#

集合(set)是一种“无序、不重复”的数据结构,用来存储一组唯一的元素。 (不能存储字典和列表)

创建方式:

  1. 使用花括号{}
  2. 使用set()函数——s=set(可迭代对象)

删除:del 集合对象

集合操作符:#

操作符含义示例结果
``并集`{1,2}
&交集{1,2} & {2,3}{2}
-差集{1,2} - {2,3}{1}
^交集的补集{1,2} ^ {2,3}{1,3}
<=子集{1} <= {1,2}True
<真子集{1} < {1,2}True
>=超集{1,2} >= {1}True
>真超集{1,2} > {1}True

集合操作方法:#

s.add(x)——如果x不在s集合中,添加到s集合中

s.remove(x)——将集合s中x删除

s.clear()——清空集合中所有元素

结构模型匹配#

match data:
case pattern1:
...
case pattern2:
...
match data:
case {}:
print("空字典")
case []:
print("空列表")
case ():
print("空元组")
case _:
print("其他情况")

多值匹配:

match data1, data2:
case 1, 2:
print("data1=1, data2=2")

异常处理#

try:
xxx() #自定义函数
except Exception as e: #不写默认为Exception
print("输入错误")
raise #层层向上报错

finally 中抛出的异常会覆盖 try 中的异常

except 后接异常类型

BaseException
├── SystemExit
├── KeyboardInterrupt
└── Exception
├── TypeError #类型不对
├── ValueError #值不合法
├── IndexError #下标越界
├── KeyError #字典没这个键
└── FileNotFoundError #文件不存在

** 同时捕获多个异常** :

try:
x = int(input())
except (ValueError, TypeError):
print("输入不合法")
  • 元组
  • 只要命中其中一个就进 except
try:
代码
except 异常类型:
处理
else:
没有异常执行
finally:
一定执行

字符串#

方法#

  • 大小写转换
s = "PyThOn"
s.lower() # 'python'
s.upper() # 'PYTHON'
s.title() # 'Python'
s.capitalize() # 'Python'
  • 去除空白
s = " hello "
s.strip() # 'hello'
s.lstrip() # 'hello '
s.rstrip() # ' hello'
  • split拆分字符串 **字符串 → 列表 **
s = "1001-苹果-10"
parts = s.split("-")
print(parts)
  • join进行拼接
"分隔符".join(可迭代对象)

示例:

words = ["Python", "is", "fun"]
result = " ".join(words) # 空格分隔
print(result)
  • find()检索字符首次出现的位置(从0开始),不存在返回-1
  • index()检索字符首次出现的位置(从0开始),不存在则报错
  • count()
  • replace(_old,_new,_count)方法,将old字符串替换成new,替换次数为count(默认全部替换)
  • str.center(width[, fillchar])方法, 把字符串放到指定宽度中间,不够的地方用指定字符填充。
  • eval函数去掉最外层的引号,可变为整型
  • repr(obj)函数, 和 str() 不同,repr()会把“看不见的字符”显示出来

格式化字符串#

  1. %格式
name = "Alice"
age = 20
height = 1.68
# 字符串和整数
print("我叫%s,今年%d岁" % (name, age))
# 浮点数保留两位小数
print("我的身高是%.2f米" % height)
  1. str.format()
name = "Alice"
age = 20
height = 1.6789
# 按顺序填充
print("我叫{},今年{}岁".format(name, age))
# 使用关键字
print("我叫{name},身高{h:.2f}米".format(name=name, h=height))
# 指定位置
print("名字:{0}, 年龄:{1}, 再次打印名字:{0}".format(name, age))
s="helloworld"
print('{0:*<20}'.format(s)) #左对齐
print('{0:*>20}'.format(s)) #右对齐
print('{0:*^20}'.format(s)) #居中对齐
#print(s.center(20,'*'))
  1. f-string

字符串的编码和解码#

  • 编码 encodestr → bytes解码 decodebytes → str
s='你好世界'
scode=s.encode(encoding='utf-8')
scode2=scode.decode(encoding='utf-8')
print(scode)
print(scode2)

数据的验证#

方法作用
.isdigit()判断字符串是否只包含数字
.isalpha()判断是否只包含字母
.isalnum()判断是否只包含字母和数字
.isspace()判断是否只包含空格
.startswith()
/ .endswith()
判断开头或结尾

enumerate()函数#

enumerate(iterable, start=0)
  • iterable:可迭代对象(列表、字符串、元组等)
  • start:索引起始值,默认是 0
  • eg:将[a, b, c]变成(0, a), (1, b), (2, c)

深拷贝和浅拷贝#

浅拷贝: 创建一个容器,容器里的元素地址不变

import copy
lst1 = [1, 2, [3, 4]]
lst2 = lst1.copy() # 方法一
lst3 = lst1[:] # 方法二
lst4 = copy.copy(lst1) # 方法三

深拷贝 : 创建一个**完全独立的新对象, 所有层级都复制 **

import copy
lst1 = [1, 2, [3, 4]]
lst2 = copy.deepcopy(lst1)

推导式#

推导式(Comprehension) 是一种用更简洁、更优雅的语法来生成列表、字典、集合或生成器的方式。

推导式 = 简洁版的 for 循环 + 条件判断,用来构建新的数据结构。

例如:

nums= [1,2,3,4,5,6]
my_list = [i for i in nums]
  • 第一个i表示为需要添加到新列表中的元素,改为i**2则为i的平方添加到my_list

函数#

参数类型(很重要也很实用)#

  • 普通参数
def f(a, b):
...

  • 默认参数
def greet(name="Nanzhi"):
print("Hello", name)

匿名函数#

lambda arguments: expression

示例:

x = lambda a : a + 10
print(x(5))

  • 可变参数(不定长)
  • args — 接收多个位置参数
def sum_all(*nums):
print(nums)

nums 是一个元组。


  • kwargs — 接收多个键值对参数
def info(**data):
print(data)

data 是一个字典。

lambda 参数1, 参数2, ...: 表达式
f = lambda x: x + 1
print(f(5)) # 6

  • 局部变量和全局变量
x = 10 # 全局变量
def foo():
y = 5 # 局部变量

函数内部不能直接修改全局变量,除非用 global

def foo():
global x
x = 20

函数也是“第一类对象”(很高级但很重要)

Python 中函数可以:

  • 赋值给变量
  • 当作参数传给函数
  • 放进列表、字典
  • 作为返回值返回

例子:

def hello():
print("Hi")
f = hello
f() # 等价于 hello()

内置函数#

  • isinstance(object, classinfo)object :要检查的对象,classinfo :类型或类型元组(可以同时检查多种类型),返回值 :布尔值( True 或 False )

面向对象#

  • 类是模版,实例/对象是根据模板生成的具体东西,类定义属性和行为,对象拥有这些属性并能执行这些行为。

类定义写法 :

class 类名:
# 类体(属性 + 方法)
pass

定义类属性 & 实例属性#

class Student:
school = "xxx_university" #类属性
def __init__(self,name):
self.name = name #实例属性
类型属于谁访问方式
类属性类本身所有对象共享Person.species
实例属性每个对象独立持有p.name

动态绑定属性

a.gender = '男' #动态添加属性
print(f"我是{a.gender}生")

实例方法#

定义在类中的函数,称为方法,自带一个参数self

实例方法如示例调用

def show(self,age):
self.age = age
print(f"我今年{se lf.age}岁了")
a=Student("xiaomin")
a.show(18)

静态方法#

  • 使用@staticmethod修饰的方法,不需要self/cls属性
  • 不能调用实例属性和实例方法
class Person:
@staticmethod
def test():
print("静态方法不能使用实例属性和实例方法")

类方法#

  • cls指向类本身
class MyClass:
@classmethod
def my_class_method(cls):
print(cls)
  • 类方法可以通过 类或实例 修改类属性。

动态绑定方法

a.func=introduce #函数的一个赋值
#func是a对象的方法
a.func() #调用

创建类对象与调用#

  • 传入两个参数因为__init__方法中有两个形参,是自带的属性,无需手动传入
  • 实例属性、类属性通过打点调用
  • 实例方法使用对象名进行打点调用
  • 静态方法、类方法使用类名打点调用
stu=Student('nz',18) #创建对象
print(stu.name,stu.age) #调用实例属性
print(Student.school) #调用类属性
stu.show() #调用实例方法
Student.sm() #调用静态方法
Student.cm() #调用类方法

权限控制#

class Student():
def __init__(self,name,age,gender):
self._name = name #self_name受保护,只能本类和子类访问
self.__age = age #self.__age表示私有的,只能类本身去访问
self.gender = gender #普通的实例属性
def _func1(self): #受保护的
print("子类及本身可以访问")
def __func2(self): #私有的
print("只有定义的类可以访问")
def show(self): #普通的实例方法
self._func1() #类本身访问受保护的方法
self.__func2() #类本身访问私有方法
print(self._name) #受保护的实例属性
print(self.__age) #私有实例属性
stu=Student("xiaomin",18,"男")
stu.show()

访问私有成员#

示例:

class Person:
def __init__(self):
self.__age = 18
def __secret(self):
print("这是秘密")
def get_age(self):
return self.__age
  1. 方法一:
p = Person()
print(p.get_age())
  1. 方法二(可行但不推荐)——名称重整:
__attr → _类名__attr
  • 访问私有属性:print(p._Person__age)
  • 访问私有方法:p._Person__secret()

属性的设置#

@property

  1. **只读属性(getter) **
class Person:
def __init__(self, age):
self._age = age # 内部属性
@property
def age(self):
return self._age

使用方式:

p = Person(18)
print(p.age) # 看起来是属性
#实际上执行 Person.age(p)
  1. **可写属性(setter) **
class Person:
def __init__(self, age):
self._age = age
@property
def age(self):
return self._age
@age.setter #属性名.setter
def age(self, value):
if value < 0:
raise ValueError("age must be non-negative")
self._age = value
p.age = 20 # 自动调用 setter

继承#

它指的是定义一个新,而对现有类的进行很少修改或没有修改。新类称为派生(或子)类,而从其继承的新类称为基(或父)类

class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def show(self):
print(f"大家好,这里是{self.name},今年{self.age}")
#Student继承Person类
class Student(Person):
def __init__(self,name,age,id):
super().__init__(name,age) #调用父类的初始化方法
self.id = id
#Doctor继承Person类
class Doctor(Person):
def __init__(self, name, age,department):
super().__init__(name, age)
self.department = department
#创建一个子类对象
stu=Student("xiaomin",18,"1001")
stu.show()
doctor=Doctor("zhangsan",30,"内科")
doctor.show()

多继承#

class FatherA():
def __init__(self,name):
self.name = name
def showA(self):
print(f"我是父类A中的方法")
class FatherB():
def __init__(self,age):
self.age = age
def showB(self):
print(f"我是父类B中的方法")
#多继承
class Son(FatherA,FatherB):
def __init__(self,name,age,id):
FatherA.__init__(self,name) #调用父类A的初始化方法
FatherB.__init__(self,age) #调用父类B的初始化方法
self.id = id
son=Son("xiaoming",18,"1001")
son.showA()
son.showB()

方法重写#

  • 优先调用子类的方法
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def show(self):
print(f"大家好,这里是{self.name},今年{self.age}")
#Student继承Person类
class Student(Person):
def __init__(self,name,age,id):
super().__init__(name,age) #调用父类的初始化方法
self.id = id
def show(self):
super().show() #调用父类中的方法
print(f"我的学号是{self.id}")
#Doctor继承Person类
class Doctor(Person):
def __init__(self, name, age,department):
super().__init__(name, age)
self.department = department
#创建一个子类对象
stu=Student("xiaomin",18,"1001")
stu.show()
doctor=Doctor("zhangsan",30,"内科")
doctor.show()

构造函数#

  • 构造函数(constructor)指的是类中的一个特殊方法,其基本形式为:
class Person:
def __init__(self, name, age):
self.name = name # 给对象绑定属性
self.age = age
p = Person("Tom", 20) # 自动调用 __init__
class CuteCat:
def __init__(self,cat_name,cat_age,cat_color):
self.name = cat_name
self.age = cat_age
cat1 = CuteCat("jojo", 12,"orange")
print(f"{cat1.name} is {cat1.age} years old")

构造函数的作用:

  • ✔ 设置对象属性
self.name = name
  • ✔ 初始化对象状态
self.score = 0

无参数构造函数示例 :

class Test:
def __init__(self):
print("构造函数被调用了")
t = Test()


文件操作#

上下文管理器#

上下文管理器(Context Manager)就是一个能被 with 语句管理进入和退出过程的对象。

换句话说:

只要一个对象定义了 **__enter__****__exit__** 方法,它就是上下文管理器。

class MyOpen:
def __init__(self,filepath):
print("Entering constructor of MyOpen")
self.filepath = filepath
def __enter__(self):
print("Ent ering __enter__ of MyOpen")
return self.filepath
def __exit__(self,exc_type,exc_value,traceback):
print("Entering __exit__ of MyOpen")
with MyOpen('data.txt') as file:
print(f"the value of file is {file}")

上下文管理器必须实现两个方法#

  1. __enter__(self) :进入 with 块之前自动执行,返回值会赋给 as 后面的变量
  2. __exit__(self, exc_type, exc_val, exc_tb): 结束 with 块后自动执行,无论是否发生异常都会执行,可以决定要不要让异常继续向外抛出

with的执行流程:

1. 调用 obj = 表达式
2. 调用 obj.__enter__()
3. 执行 with 代码块
4. 调用 obj.__exit__()

文件读取#

  • read:读取文件的全部内容
  • readline():逐行读取
  • readlines():读取所有行并存储为**列表 **
f = open("./data.txt","r",encoding="utf-8")
print(f.read()) #内括号可以写入读取的字节数
f = open("./data.txt","r",encoding="utf-8")
lines = f.readlines()
for line in lines:
print(line)
f.close() #关闭文件,释放资源
  • 使用with关键字(with 语句最典型的用途是处理那些需要在使用后明确释放或关闭的资源):with 表达式 as 变量:

文件操作就是一个上下文管理器

# data.txt 在 with 块结束后,无论是否发生错误,都会自动调用 file.close() 方法
with open('data.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
# 在 with 块外部,文件已经被安全关闭

文件写入#

  • 写入模式 ‘w’:如果文件存在,内容会被清空
  • 使用’a’参数打开,为附加模式
  • 使用’r+’参数,同时支持读写文件
with open('output.txt', 'w', encoding='utf-8') as f:
# 写入第一行,必须手动添加换行符
f.write("这是写入文件的第一行。\n")
# 写入第二行
f.write("这是第二行内容。\n")
# 'r+': 读写模式,指针在开头
with open("./data.txt", "r+", encoding="utf-8") as f:
f.write("hello!\n") # 写入,指针移动到写入内容的末尾
f.write("yoo") # 继续写入,指针移动到新的末尾
# --- 关键步骤 ---
# 将文件指针移回文件开头 (位置 0)
f.seek(0)
# 重新读取整个文件的内容
print(f.read())
模式含义
"r"只读(文本)
"w"只写(文本,覆盖)
"a"追加(文本)
"rb"二进制读
"wb"二进制写
"ab"二进制追加
"r+"读写

打包与解包#

单*#

  • * (单个星号) 的作用 : 主要用于**序列(如列表、元组)**的打包和解包。
numbers = [1,2,3,4,5]
first,*rest = numbers
print(first)
print(rest)
1
[2, 3, 4, 5]

打包成一个序列:

def print_values(*args):
for arg in args:
print(arg)
print_values(1,2,3,4)

解包:

list1 =[1,2,3]
tuple1 = (4,5,6)
merged = [*list1,*tuple1]
print(merged)
# [1, 2, 3, 4, 5, 6]

person解包成Alice30两个值:

def greet(name,age):
print(f"hello{name},you are {age} years old")
person =('Alice',30)
greet(*person)

双**#

  • ** 主要用于字典 (Dictionary) 的打包和解包。

打包:

def example(**kwargs):
for key,value in kwargs.items():
print(f"{key}={value}")
example(a=1,b=2)

解包(字典):

def create_profile(name,age,email):
print(f"name : {name}")
print(f"age : {age}")
print(f"email : {email}")
option = {
"name":"tony",
"age":18,
"email":"tony@qq.com"
}
create_profile(**option)

装饰器#

  • 修饰器本质上是一个以函数作为参数,并返回新函数的函数。

**装饰器的基本用法: **

def my_decorator(func):
def wrapper():
print("Before function")
func()
print("After function")
return wrapper
@my_decorator
def hello():
print("Hello!")
hello()

输出:

Before function
Hello!
After function
def hello():
...

设计模式#

工厂模式#

把“创建对象”的代码,集中放到一个地方管理

# 工厂模式
class DatabaseConnection:
def __init__(self,host,port,username,password):
self.host = host
self.port = port
self.username = username
self.password = password
def connect(self):
return f'Connecting to database at {self.host}:{self.port} with username {self.username}'
def connection_factory(db_type):
db_config ={
'main':{
'host': 'localhost',
'port': 3306,
'username': 'root',
'password':'password123'
},
'analytics':{
'host': '192.168.1.1',
'port': 5432,
'username': 'admin',
'password':'pass3'
},
'cache':{
'host': '10.0.0.1',
'port': 27017,
'username': 'cacher',
'password':'cipher'
}
}
return DatabaseConnection(**db_config[db_type]) #字典解包
def client():
main_db = connection_factory('main')
analytics_db = connection_factory('analytics')
cache_db = connection_factory('cache')
print(main_db.connect())
print(analytics_db.connect())
print(cache_db.connect())
client()

单例模式#

class DatabaseConnection:
_instance = None
def __new__(cls,*args,**kwargs) -> Self:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance

模块#

导入自己写的模块#

  1. 在同一目录下,以下为目录模板:
project/
main.py
moduleA.py

moduleA.py内容:

def hello():
print("Hello from module!")

main.py 中 :

import moduleA
mytool.hello()
  1. 在不同目录下,__init__.py的用法:
my_package/
__init__.py
util.py
import my_package

相当于导入了__init__.py

__init__.py的使用:

  1. 包的初始化
  2. 管理包接口

相对导入#

  • 相对导入的符号:
写法含义
.当前包(current package)
..上一级目录(parent package)
...上上级目录(grandparent package)

示例目录结构#

project/
packageA/
__init__.py
a.py
b.py
sub/
__init__.py
c.py
  • 同级目录导入:
from . import
# from .a import func_a 导入a某个函数

不写点 Python 会从项目根路径开始查找 a 模块,而不是同级目录。

from package.a import func_a = from .a import func_a

非同级目录的导入#

  • from packageA.a import x的过程

路径 packageA.a 其实是:

packageA ← 一个包(必须先被加载)
packageA.a ← 包里的模块

所以导入 packageA.a 的过程是:

import packageA
import packageA.a

魔术方法#

<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">__all__</font> 是一个模块级别的变量(通常是一个字符串列表),用于定义当客户端代码使用 <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">from module import *</font> 时,哪些名称会被导入到当前命名空间。

mymodule.py
__all__ = ['public_func', 'PublicClass']
def public_func():
return "I'm public!"
def _private_func():
return "I'm private (by convention)!"
class PublicClass:
pass
class _PrivateClass:
pass

json的基础使用和操作#

  1. json导出至文件
import json
user = {}
user['name'] = input('请输入姓名')
user['age'] = int(input('请输入年龄'))
contents = json.dumps(user) #字典 -> 字符串
with open("user_info.json", "r+", encoding="utf-8") as f:
f.write(contents)
  1. 读取json文件
import json
with open("./user_info.json","r",encoding="utf-8") as f:
contents = f.read()
user = json.loads(contents) # 字典 <- 字符串
print(f'欢迎回来{user['name']}')

迭代器和生成器#

for循环原理:

it =iter(my_str) #my_str.__iter__(),my_str为可迭代对象,it为迭代器
while True:
try:
print(next(it)) #调用迭代器的next方法
except StopIteration: #无法获取迭代器的下一个值
break


示例:

class MyNumbers:
def __init__(self):
self.num = 1
def __iter__(self):
return self #获取迭代器自己
def __next__(self):
if self.num <= 3:
x = self.num
self.num += 1
return x
else:
raise StopIteration

生成器函数#

函数里只要出现 yield,这个函数就变成 生成器函数

def generator(n):
for i in range(n):
print('before yield')
yield i
print("after yield")
gen = generator(3) #gen 为生成器
print(next(gen)) #生成0后退 出生成器函数
print("---")
for i in gen:
print(i)
before yield
0
---
after yield
before yield
1
after yield
before yield
2
after yield

柯里化#

  • 把一个接受多个参数的函数,变成一系列只接受一个参数的函数。

柯里化后函数

def add(a):
def inner(b):
return a + b
return inner

执行:

add(3) → 返回 inner 函数,相当于固定a的值
inner(5) → 计算 3 + 5

functools.partial(func, 参数1, 参数2, ...)
示例:

from functools import partial
def multiply(a, b):
return a * b
double = partial(multiply, 2)
print(double(5))

多线程#

from time import sleep,time
from threading import Thread
start_time = time()
def dnownload_img(url):
sleep(1)
print(f'{url} download complete')

线程池:

from decimal import MAX_EMAX
from time import time,sleep
from concurrent import futures #线程池
start_time = time()
def download_img(url):
sleep(1)
return (f'{url} download complete')
with futures.ThreadPoolExecutor(max_workers=10) as excutor:
results = excutor.map(download_img,range(10)) #range(10)作为download_img的参数
for result in results:
print(result)
  • **守护线程(daemon=True):**主线程一结束,**不管它干没干完,直接结束;**不会影响程序退出

枚举#

  • 定义枚举
import enum
class ChapterResult(enum.Enum):
SUCCESS = 0
ERROR = 1
NOT_OPEN = 2
PENDING = 3
  • 使用枚举
result = ChapterResult.SUCCESS
  • 属性
属性含义示例
result.name枚举成员名"ERROR"
result.value实际存储的值1

遍历查看member

from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
for c in Color:
print(c.name,c.value)

enumbool一样,也具有唯一实例性和不可变

数据解析#

正则表达式#

元字符含义
.匹配任意 一个 字符(除换行)
\d数字 [0-9]
\D非数字
\w字母、数字、下划线
\W非字母数字下划线
\s空白字符(空格、\t
\n
\S非空白字符
``
[...]匹配字符组中的字符
[^...]除了字符组里的内容
限定符(控制前面原字符出现的次数)含义
*0 次或多次
+1 次或多次
?0 次或 1 次
{n}恰好 n 次
{n, }至少 n 次
{n,m}n 到 m 次

^从开头开始匹配,$结尾匹配

贪婪匹配和惰性匹配

.* 贪婪匹配(尽可能多地匹配结果)
.*? 惰性匹配(尽可能少地匹配结果 -> 回溯)

re模块#

  • re.match(pattern, string)—— 只在字符串“开头”尝试匹配

示例:

import re
text = "123abc"
m = re.match(r"\d+", text)
print(m.group()) # 123
  • re.search(pattern, string)—— 在整个字符串中查找第一个匹配结果

示例:

text = "abc123def456"
m = re.search(r"\d+", text)
print(m.group()) #从匹配到的结果拿数据
# 123
  • re.findall(pattern, string)—— 返回所有匹配结果的列表

示例(注意有无分组):

re.findall(r"(\d+)", text)
# ['123', '456', '789']
re.findall(r"(\d+)([a-z]+)", "123abc456def")
# [('123', 'abc'), ('456', 'def')]
  • re.finditer返回的是迭代器
  • re.sub(pattern, repl, string)

示例:

text = "电话:123-456-789"
new = re.sub(r"\d", "*", text)
print(new)
# 电话:***-***-***
  • re.split(pattern, string)—— 按正则规则切字符串

示例:

text = "apple,banana;orange|grape"
parts = re.split(r"[,;|]", text)
print(parts)
# ['apple', 'banana', 'orange', 'grape']
  • 预加载,提前把正则对象加载完毕:
obj = re.compile(r"\d+")
for item in x:
obj.finditer(item)
obj = re.compile(r"\d+")
#直接把加载好的正则使用
result = obj.findall(text)

分组:

  1. 普通分组
(\d+)
  • 自动编号:1、2、3……;用 group(1)group(2)
import re
m = re.search(r"(\d+)-(\w+)", "123-abc")
print(m.group(1)) # 123
print(m.group(2)) # abc
  1. 命名分组
(?P<name>\w+)

示例:

m = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})", "2026-02")
print(m.group("year")) # 2026
print(m.group("month")) # 02
import re
s="""
<div class='西游记'><span id='10010'>中国联通</span></div>
<div class='西游记'><span id='10086'>中国移动</span></div>
"""
obj =re.compile(r"<span id='(?P<id>\d+)'>(?P<name>.*?)</span>")
result =obj.finditer(s)
for item in result:
id = item.group("id")
print(id)
name=item.group("name")
print(name)

time模块#

  • time 提供的是偏底层、面向系统时间的功能

常用函数:

  • time.time() —— 当前时间戳
  • time.localtime([sec]) —— 本地时间结构
time.struct_time(
tm_year, # 年
tm_mon, # 月 (1-12)
tm_mday, # 日 (1-31)
tm_hour, # 时 (0-23)
tm_min, # 分 (0-59)
tm_sec, # 秒 (0-61)
tm_wday, # 星期 (0=周一)
tm_yday, # 一年中的第几天
tm_isdst # 是否夏令时
)
  • time.ctime()——返回当前时间戳的字符串表示
  • time.strftime() —— 时间 → 字符串
now = time.localtime()
s = time.strftime("%Y-%m-%d %H:%M:%S", now)
print(s)

输出

2025-12-24 21:30:00

常用格式符:

格式含义
%Y
%m
%d
%H
%M
%S
  • time.strptime() —— 字符串 → 时间 , 返回 struct_time
t = time.strptime("2025-12-24 21:30:00", "%Y-%m-%d %H:%M:%S")

loguru库#

  • 安装:pip install loguru

快速入门#

  • 严重程度逐渐增加
级别描述
TRACE最详细的日志,调试级别
DEBUG调试信息
INFO普通信息
SUCCESS成功信息
WARNING警告
ERROR错误
CRITICAL严重错误,程序可能无法继续
from loguru import logger
logger.debug("调试信息")
logger.info("普通信息")
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误")

add方法#

logger.remove() #移除了 loguru 的所有默认 sink
logger.add("file.log", rotation="5 MB", retention="10 days", level="INFO")

参数解释:

  • rotation → 日志文件达到多少大小或时间就切分
  • retention → 保留多长时间的日志
  • level → 最低记录级别

tqdm库#

  • tqdm 是 Python 中非常流行的 进度条库
  • 安装:**pip install tqdm**

手动更新#

  • pbar.update(n) 表示在当前进度基础上增加 n 个 item
pbar = tqdm(total=100)
pbar.update(10)
sleep(2)
pbar.update(20)
sleep(2)
pbar.update(70)
pbar.close()

使用with语句:

with tqdm(total=100) as pbar:
pbar.update(10)
sleep(2)
pbar.update(20)
sleep(2)
pbar.update(70)

write用法#

  • 功能:在进度条上方打印消息,不破坏 tqdm 进度条
tqdm.write(msg, file=sys.stdout, end='\n', nolock=False)

参数:

参数说明
msg要打印的消息(字符串)
file输出流,默认 sys.stdout
end行尾符,默认 \n
nolock多线程/多进程环境下是否使用锁,默认 False
(安全)

argparse 模块#

  • argparse 是 Python 的解析命令行参数的标准库

命令行解析器#

import argparse
parser = argparse.ArgumentParser() #创建解析器parser
parser.add_argument("--name") #添加参数
args = parser.parse_args() #解析参数
print(args.name)

终端执行:

python test.py --name Tom

输出:

Tom
  • parser.parse_args() 返回Namespace类,打点访问具体值
参数作用
name / —name参数名
help帮助说明
type类型
default默认值
required是否必填
choices可选值
action行为方式
  • 位置参数
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("filename") # 定义一个“位置参数”
args = parser.parse_args()
print(args.filename)
  • 限定取值
parser.add_argument("--mode", choices=["train", "test"])
  • **action**参数:

默认行为:store 最常用:store_true store_false

count:统计出现次数

append:可以写多次 :

python main.py --tag A --tag B --tag C

结果:

args.tag == ["A", "B", "C"]
  • 布尔开关参数
parser.add_argument("--debug", action="store_true")
python main.py --debug
args.debug == True

没写就是 False。

  • sys.argv是命令行参数(脚本名称是 sys.argv[0] )

configparser 模块#

  • 配置文件解析模块

config.ini

[database]
host = localhost
port = 3306
user = root
password = 123456
[server]
debug = true
timeout = 30

configparser.ConfigParser.items()

基本用法:

import configparser
config = configparser.ConfigParser()
config.read("config.ini", encoding="utf-8")
print(config.sections()) # 所有 section
print(config["database"]["host"]) # 取值(字符串)
print(config.get("database", "port"))

urllib.request模块#

urllib.requestpython 自带的最基础网络库

from urllib.request import urlopen
url = "http://www.baidu.com"
resp = urlopen(url)
with open("msg.txt","wb") as f:
f.write(resp.read())
print(resp.read())

解码:

print(resp.read().decode("utf-8"))

requests模块#

  1. 首个爬虫程序
import requests
url = "http://baidu.com"
resp = requests.get(url)
resp.encoding = "utf-8"
print(resp.text)
  1. 使用get请求
import requests
content = input('请输入你要检索的内容:')
url = f"https://sogou.com/web?query={content}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
}
resp = requests.get(url, headers=headers)
resp.encoding = "utf-8"
print(resp.text)
  1. 很多参数的get请求
import requests
url = "https://movie.douban.com/j/chart/top_list"
data = {
"type": "13",
"interval_id": "100:90",
"action": "",
"start": "0",
"limit": "20"
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
}
resp = requests.get(url,params=data,headers=headers)
print(resp.text)
  1. 使用post请求
import requests
url = "https://fanyi.baidu.com/sug"
data = {
"kw": input("请输入一个单词:")
}
resp = requests.post(url, data=data)
print(resp.json()["data"]) # 返回字典
  1. session

自动保存 Cookie,自动带上之前的 Cookie,复用连接(更快),统一管理 headers、params、auth 等

import requests
session = requests.Session()
# 登录
session.post("https://xxx.com/login", data={
"user": "a",
"pwd": "123"
})
# 已经是“登录态”
resp = session.get("https://xxx.com/profile")
print(resp.text)
  1. mountrequests.Session 里一个比较高级但非常有用的接口,主要用于:“给不同协议或不同域名,绑定不同的“连接适配器(HTTPAdapter)”

常见用法:

  1. 给 http / https 设置重试策略
from requests import Session
from requests.adapters import HTTPAdapter
s = Session()
s.mount("http://", HTTPAdapter(max_retries=3))
s.mount("https://", HTTPAdapter(max_retries=3))
s.get("https://example.com")
  1. 只对某个域名生效
s.mount("https://api.example.com", HTTPAdapter(max_retries=10))
  1. 控制连接池大小(进阶)
adapter = HTTPAdapter(
pool_connections=10,
pool_maxsize=20,
max_retries=5
)
s.mount("https://", adapter)

参数含义:

  • pool_connections:连接池数量
  • pool_maxsize:每个池最多多少连接
  • max_retries:重试次数
  1. proxies代理
import requests
url="http://baidu.com"
#代理
proxy={
"http": "xxx",
"https": "xxx"
}
resp = requests.get(url,proxies=proxy)
resp.encoding="utf-8"
print(resp.text)
  1. timeout
  • timeout 用来限制:请求最多等多久;如果超过这个时间还没成功,就直接抛异常,不再傻等。

bs4模块#

pip install lxml
  • 基本使用方式
import requests
from bs4 import BeautifulSoup
url = "https://example.com"
html = requests.get(url).text
soup = BeautifulSoup(html, "lxml")

获取标签、获取文本

soup.h1 #soup.find("h1")
soup.h1.text #soup.h1.string

findfind_all(找所有)

soup.find("p", class_="text")
方法功能返回值找不到时
soup.find(name, attrs, ...)查找第一个匹配的标签单个 Tag
对象
None
soup.find_all(name, attrs, ...)查找所有匹配的标签包含 Tag
对象的list
空列表 []

进阶:使用CSS选择器

  • soup.select('selector'):返回所有匹配元素的列表。
  • soup.select_one('selector'):返回第一个匹配的单个元素

文本提取:

方法说明示例
tag.get_text()获取所有内部文本(包括子孙),可传分隔符tag.get_text(strip=True)
.string仅当标签内部只有一个文本节点时有效,否则为 None<p>Hello</p>
可以得到 'Hello'
.strings生成器,返回所有子孙文本节点适合处理混杂标签与文本
.stripped_strings.strings
,但自动去除空白
最常用于抽取纯文本列表

pathlib#

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Python笔记(自用)
https://blog.litkg.com/posts/python/
作者
南栀
发布于
2026-06-17
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录