Python学习笔记——其一
该笔记持续更新,仅更新部分,如有错误请在评论区指正,谢谢🙏
首次博客更新2025-12-29
虚拟环境
基本语法
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.")
列表
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)
- 方法:
对象.方法名(...)
- 函数:
函数名.(对象)
字典
contacts = {
("xioamin",23):"111111111",
("xiaohua",24):"222222222"
}
del contacts[("xioamin",23)]
contacts[("xiaomei",24)] = "123131"
print(contacts)
print(len(contacts))
- 访问字典:
- 使用
[]访问
- 使用
student_grades = {
"语文": 90,
"数学": 95,
"英语": 88,
"科学": 92
}
# 访问 '数学' 键对应的值
math_score = student_grades["数学"]
print(math_score) # 输出: 95
2. 使用`.get()` 方法# 1. 键存在:返回对应的值
english_score = student_grades.get("英语")
print(english_score) # 输出: 88
# 2. 键不存在:返回默认值 None
history_score_default = student_grades.get("历史")
print(history_score_default) # 输出: None
# 3. 键不存在:返回指定的默认值(例如 0)
history_score_custom = student_grades.get("历史", 0)
print(history_score_custom) # 输出: 0
| 写法 | 键不存在时 |
|---|---|
q_info["images"] | ❌ 直接抛 KeyError |
q_info.get("images") | ✅ 返回 None |
try...finally
- 基本结构:
try:
# 可能会出错的代码
finally:
# 无论有无异常,都会执行这里
finally 里的代码 一定会执行,即使 _try_ 中发生异常,也会执行 _finally_
- 常见用途:
a. 关闭文件、释放资源:
f = open("a.txt", "w")
try:
f.write("hello")
finally:
f.close() # 不管中间是否出错,都关闭文件
b. 关闭网络连接 / 数据库连接
...
try...except...finally三者一起使用
try:
risky_code()
except Exception as e:
print("出现错误:", e)
finally:
print("无论怎样我都会执行")
执行顺序:
1. 执行 `try`
2. 出错则进入 `except`(不出错就跳过)
3. 最后 **一定执行**`finally`
finally中抛出的异常会覆盖try中的异常
枚举
- 定义枚举
import enum
class ChapterResult(enum.Enum):
SUCCESS = 0
ERROR = 1
NOT_OPEN = 2
PENDING = 3
- 使用枚举
result = ChapterResult.SUCCESS
- 属性
| 属性 | 含义 | 示例 |
|---|---|---|
result.name | 枚举成员名 | "ERROR" |
result.value | 实际存储的值 | 1 |
其他用法
repr(obj)函数, 和str()不同,repr()会把“看不见的字符”显示出来rstrip()是 Python 字符串的一个方法,用来 去掉字符串右侧(末尾)的空白字符或指定字符。
函数
参数类型(很重要也很实用)
- 普通参数
def f(a, b):
...
- 默认参数
def greet(name="Nanzhi"):
print("Hello", name)
- 可变参数(不定长)
- args — 接收多个位置参数
def sum_all(*nums):
print(nums)
nums 是一个元组。
- kwargs — 接收多个键值对参数
def info(**data):
print(data)
data 是一个字典。
- 局部变量和全局变量
x = 10 # 全局变量
def foo():
y = 5 # 局部变量
函数内部不能直接修改全局变量,除非用 global:
def foo():
global x
x = 20
函数也是“第一类对象”(很高级但很重要)
Python 中函数可以:
- 赋值给变量
- 当作参数传给函数
- 放进列表、字典
- 作为返回值返回
例子:
def hello():
print("Hi")
f = hello
f() # 等价于 hello()
面向对象
类是模版,实例/对象是根据模板生成的具体东西,类定义属性和行为,对象拥有这些属性并能执行这些行为。
类定义写法 :
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"我今年{self.age}岁了")
a=Student("xiaomin")
a.show(18)
静态方法
- 使用
@staticmethod修饰的方法,不需要self/cls属性 - 不能调用实例属性和实例方法
class Person:
@staticmethod
def test():
print("静态方法不能使用实例属性和实例方法")
类方法
cls指向类本身
class Person:
@staticmethod
def util():
print("工具方法")
动态绑定方法:
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
- 方法一:
p = Person()
print(p.get_age())
- 方法二(可行但不推荐)——名称重整:
__attr → _类名__attr
- 访问私有属性:
print(p._Person__age) - 访问私有方法:
p._Person__secret()
属性的设置
@property
- 只读属性(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)
- 可写属性(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()
推导式
推导式(Comprehension) 是一种用更简洁、更优雅的语法来生成列表、字典、集合或生成器的方式。
推导式 = 简洁版的 for 循环 + 条件判断,用来构建新的数据结构。
例如:
nums= [1,2,3,4,5,6]
my_list = [i for i in nums]
- 第一个
i表示为需要添加到新列表中的元素,改为i**2则为i的平方添加到my_list
文件操作
上下文管理器
上下文管理器(Context Manager)就是一个能被 with 语句管理进入和退出过程的对象。
换句话说:
只要一个对象定义了
**__enter__**和**__exit__**方法,它就是上下文管理器。
class MyOpen:
def __init__(self,filepath):
print("Entering constructor of MyOpen")
self.filepath = filepath
def __enter__(self):
print("Entering __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}")
上下文管理器必须实现两个方法
__enter__(self):进入 with 块之前自动执行,返回值会赋给as后面的变量__exit__(self, exc_type, exc_val, exc_tb): 结束 with 块后自动执行,无论是否发生异常都会执行,可以决定要不要让异常继续向外抛出
with的执行流程:
1. 调用 obj = 表达式
2. 调用 obj.__enter__()
3. 执行 with 代码块
4. 调用 obj.__exit__()
异常抛出(raise)
- 基本用法(直接抛出一个异常类型):
raise ValueError("参数不合法")
报错:
ValueError: 参数不合法
文件读取
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())
打包与解包
单*
*(单个星号) 的作用 : 主要用于序列(如列表、元组)的打包和解包。
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解包成Alice和30两个值:
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():
...
模块
导入自己写的模块
- 在同一目录下,以下为目录模板:
project/
main.py
moduleA.py
moduleA.py内容:
def hello():
print("Hello from module!")
main.py 中 :
import moduleA
mytool.hello()
- 在不同目录下,
__init__.py的用法:
my_package/
__init__.py
util.py
import my_package
相当于导入了
__init__.py
__init__.py的使用:
- 包的初始化
- 管理包接口
相对导入
- 相对导入的符号:
| 写法 | 含义 |
|---|---|
. | 当前包(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 funca = # from .a import funca
非同级目录的导入
from packageA.a import x的过程
路径 packageA.a 其实是:
packageA ← 一个包(必须先被加载)
packageA.a ← 包里的模块
所以导入 packageA.a 的过程是:
import packageA
import packageA.a
多线程
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(安全) |