python 基础

创建虚拟环境

指令格式: python -m venv 目录名

启动环境指令:

1
2
3
4
5
windows:
目录名\Scripts\activate

Linux:
source ./目录名/bin/activate

退出指令:

1
deactivate

注释

单行注释以 # 开头。

多行注释使用三个单引号 ’’’ 或三个双引号 ““” 将注释包含其中。

数据类型

变量赋值时自动判断数值的类型。

变量后可以加冒号: 指定类型。(但指定int,赋值str也能正常运行。这是给IDE和自己看的。)

Number(数字)

1
age: int = 256

String(字符串)

1
name: str = "isaac"

bool(布尔类型)

1
2
is_empty: bool = True
is_empty: bool = False

List(列表)

可变,有序,元素可重复

元素类型支持数字,字符串,列表等等。

1
2
users: list = []
users: list = ["102", "xiaoming", "Tac"]

Tuple(元组)

不可变,有序。

1
2
3
tup: tuple = ()
tup: tuple = ("name", ) # 单个元素必须后面加一个, 否则解释器会识别为str类型。
tup: tuple = ("name", "opop", 89897)

Set(集合)

无序,元素唯一(自动去重)

1
2
empty_set: set = set() # 空集合必须使用set(), 否则会被识别为dict类型
ports_num: set = {"name", 5984, "txt", 99}

Dictionary(字典)

键值对,键唯一且不可变

1
2
3
4
5
6
7
8
9
10
server: dict = {"host": "127.0.0.1", "port": 8080, "secure": True}
user:dict = dict(name="isaac", age=26, city="BeiJing")

# 创建空字典
empty_dict1: dict = {}
empty_dict2: dict = dict()

# 元组列表转换为字典
kv_pairs:list = [("status", 200), ("msg", "OK"), ("version", "v1.0")]
api_response: dict = dict(kv_pairs)

类型转换

隐式类型转换

1
2
3
num_int = 123
num_float = 1.23
num_new = num_int + num_float #<class 'float'>

显示类型转换

1
2
3
4
5
6
7
8
int("12") #<class 'int'>
float(5) #<class 'float'>
str(667) #<class 'str'>
bool(8) #<class 'bool'>
list("abc") #<class 'list'>
tuple([1, 2]) #<class 'tuple'>
set([1,2,3]) #<class 'set'>
dict([('a', 1)]) #<class 'dict'>

注意:除了值为0,0.0,““,[],(),{},set(),None,其余值bool()皆返回True。

运算符

算数运算符

运算符 描述
+
-
*
/
%
** a**b 相当于 a^b
// 取整数(往小)9//4=2, -9//4=-3

赋值运算符

运算符 描述
=
+=
-=
*=
/=
%=
**=
//=
:= 海象运算符

海象运算符可以在判断或循环的同时,将值存入变量减少重复代码。

1
2
3
4
5
6
if len(my_list) > 3:
print(f"长度为{len(my_list)}")

# 只调用一次len
if (n := len(my_list)) > 3:
print(f"长度为{n}")

比较运算符

运算符 描述
==
!=
>
<
>=
<=

位运算符

运算符 描述
&
|
^
~
<<
>>

逻辑运算符

运算符 描述
and
or
not

成员运算符

运算符 描述
in x在y中有,返回 True
not in x在y中没有,返回 True

身份运算符

运算符 描述
is x和y指向的是同一个地址,返回True
is not x和y指向的是不同的地址,返回True

条件控制

if

1
2
3
4
5
6
if a == 20:
pass
elif a == 30:
pass
else:
pass

三元运算符

1
status = "成年" if age >= 18 else "未成年"

match

1
2
3
4
5
6
7
8
9
match age:
case 15:
pass
case 20:
pass
case 30:
pass
case _:
pass

循环

for

1
2
3
4
5
6
7
8
9
10
11
fruits = ["苹果", "香蕉", "橙子"]
for fruit in fruits:
print(f"水果: {fruit}")

for i in range(5):
print(i)

for fruit in fruits:
print(f"水果: {fruit}")
else:
print("循环正常结束")

while

1
2
3
4
5
6
7
8
9
10
count = 1
while count <= 5:
print(f"第{count}次")
count += 1

while count <= 5:
print(f"第{count}次")
count += 1
else:
print("循环正常结束")

循环正常结束就会执行else里的代码

break:彻底终止当前整个循环,跳出循环体。

continue:跳过当前这一次循环剩下的代码,直接进入下一次循环。

函数

基础

1
2
3
4
5
def example():
print("pass")

def example(name):
print(f"pass {name}")

默认参数

1
2
3
4
5
6
def example(name, age=16):
print(f"pass {name}: {age}")

example("issac") # pass issac: 16

example("issac", 50) # pass issac: 50

调用时使用参数名称

1
2
3
4
5
6
7
def example(name, age=16):
print(f"pass {name}: {age}")

example(age = 33, name = "isaac") # pass isaac: 33

# age=16 右侧的其余参数必须要有默认值
# 右侧如果不想添加默认值,可以使用强制关键字(*)

强制位置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
#  / 之前的参数必须按位置传递
def example(name, age, /, num):
print(f"pass {name}: {age} - {num}")

example("isaac", 33, num = 10) # pass isaac: 33 - 10


def example(name, age=16, /, num=20):
print(f"pass {name}: {age} - {num}")

example("isaac", num = 10) # pass isaac: 16 - 10
example("isaac", 30, num = 10) # pass isaac: 30 - 10
# 注意: 必须按顺序传递参数,/ 之前不能使用num = 10这种形式(就是按顺序也不行)

强制关键字参数

1
2
3
4
5
6
# * 之后的参数必须以名称传递

def example(name, age=16, *, num, text):
print(f"pass {name}: {age} - {num} - {text}")

example("isaac", 30, num = 10, text = "Hello") # pass isaac: 30 - 10 - Hello

可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def example(name, age=16, *args):
print(f"pass {name}: {age}")

for num in args:
print(f"num {num}")

example("isaac", 30, 1, 2, 3)

"""
输出:
pass isaac: 30
num 1
num 2
num 3
"""

关键字可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def example(name, age=16, **kwargs):
print(f"pass {name}: {age}")

for name, num in kwargs.items():
print(f"name:{name} - num:{num}")

example("isaac", 30, xiao = 1, li = 2, wang = 3)

"""
输出:
pass isaac: 30
name:xiao - num:1
name:li - num:2
name:wang - num:3
"""

lambda

1
2
3
add = lambda x, y: x + y

print(add(10, 20)) # 30

函数注解

1
2
def add(x: int, y: int) -> int:
return x + y

嵌套

1
2
3
4
5
6
7
8
9
10
def outer(x):
def inner(y):
return x + y

return inner

print(outer(10)(20)) # 30

add_five = outer(5)
print(add_five(20)) # 25

装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 不修改原函数,增加其功能。
def my_decorator(func):
def wrapper(x, y):
print("执行前...")
print(func(x, y))
print("执行后")

return wrapper

def add(x, y):
return x + y;

my_decorator(add)(10, 20)

"""
输出:
执行前...
30
执行后
"""

# 实际作用:say_hello = my_decorator(say_hello)
@my_decorator
def say_hello(x, y):
print("Hello!")

return x * y

say_hello(10, 30)

"""
输出:
执行前...
Hello!
300
执行后
"""

类

类基础

1
2
3
4
5
6
7
8
9
10
11
class Person:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age

def greet(self): # 实例方法
return f"Hello, I am {self.name}"

a = Person("isaac", 64)

print(a.greet()) # Hello, I am isaac

类属性和方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MathUitls:
version = "1.0" #类属性

@classmethod
def get_version(cls):
return cls.version

# 类属性和类方法,不用实例化直接使用
print(f"{MathUitls.version} --- {MathUitls.get_version()}")

"""
输出:
1.0 --- 1.0
"""

类静态方法

1
2
3
4
5
6
7
# 不访问类的实例或数据
class MathUitls:
@staticmethod
def add(a, b):
return a + b

print(f"num={MathUitls.add(20, 30)}") # num=50

数据类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 通过装饰器 @dataclass 自动生成 __init__, __repr__, __eq__ 等方法,是定义“纯数据对象”的最优选择。

from dataclasses import dataclass

@dataclass
class Point:
x: int
y: int

Point.x = 10

print(Point.x) # 10

a = Point(x=50, y=20)

print(a.x) # 50
print(Point.x) # 10

类属性装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 实现像访问属性一样调用方法
class Temperature:
def __init__(self, celsius):
self._celsius = celsius

@property
def fahrenheit(self):
return (self._celsius * 9 / 5) + 32

@fahrenheit.setter
def fahrenheit(self, value):
self._celsius = (value - 32) * 5 / 9

a = Temperature(60)

print(a.fahrenheit) # 140.0
a.fahrenheit = 100
print(a.fahrenheit) # 100.0

抽象基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 通过 abc 模块强制子类实现特定方法
from abc import ABC, abstractmethod

class Shape(ABC):
@abstractmethod
def area(self):
pass

class Circle(Shape):
def __init__(self, radius):
self.radius = radius

def area(self):
return 3.14 * (self.radius ** 2)

a = Circle(20)
print(a.area()) # 1256.0

类私有成员

1
2
3
4
5
6
7
8
9
10
11
12
13
# Python 没有严格的 private 关键字,但通过双下划线 __ 前缀,触发名称修饰机制来隐藏属性。
class SecureVault:
def __init__(self):
self.__secret_key = "12345" # 外部无法访问
self.num = 20

a = SecureVault()

print(a.num) # 20
print(a.__secret_key)
"""
AttributeError: 'SecureVault' object has no attribute '__secret_key'
"""

继承和多重继承

1
2
3
4
5
6
7
8
9
10
11
class Base1:
pass

class Base2:
pass

class Age(Base1):
pass

class Num(Base1, Base2):
pass

元类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 定义元类
class MustHaveNameMate(type):
def __new__(cls, name, bases, namespace, /, **kwds):
# 检查类属性字典里是否有 name
if 'name' not in namespace:
raise TypeError(f"错误:类{name}必须定义'name'属性")

# 通过效验,则正常创建类
return super().__new__(cls, name, bases, namespace, **kwds)

# 会创建成功
# 关键字参数:metaclass
class MyClass(metaclass = MustHaveNameMate):
name = "TestClass"

## 失败
class BadClass(metaclass = MustHaveNameMate):
pass

"""
输出
TypeError: 错误:类BadClass必须定义'name'属性
"""


# 全局注册表
registry = {}

class RegisterMete(type):
def __new__(cls, name, bases, namespace, /, **kwds):
new_cls = super().__new__(cls, name, bases, namespace, **kwds)

#将使用该元类的类存入字典
registry[name] = new_cls

return new_cls

class MyView(metaclass = RegisterMete): pass
class AuthView(metaclass = RegisterMete): pass

print(registry)

"""
输出:
{'MyView': <class '__main__.MyView'>, 'AuthView': <class '__main__.AuthView'>}
"""

# 添加方法
def auto_save(self):
print(f"真正保存{self.__class__.__name__}的数据...")

class AutoSaveMeta(type):
def __new__(cls, name, bases, namespace, /, **kwds):
# 把save方法塞入字典
namespace['save'] = auto_save

return super().__new__(cls, name, bases, namespace, **kwds)

class Product(metaclass = AutoSaveMeta): pass

p = Product()
p.save() # 真正保存Product的数据...

槽位类 (Slots)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 通过 __slots__ 限制实例属性的创建,减少内存占用,禁止动态添加属性。
class OptimizedClass:
__slots__ = ['name', 'id']

def __init__(self, name, id):
self.name = name
self.id = id
self.age = 10

a = OptimizedClass("isaac", 1)

"""
由于定义了age 报错了
AttributeError: 'OptimizedClass' object has no attribute 'age'
"""

异步

异步基础

异步函数使用 async def 定义,必须在事件循环中通过 await 或 asyncio.run() 运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import asyncio

async def say_hello():
print("Hello...")
await asyncio.sleep(1)
print("Hello2...")


async def say_world():
print("...World!")
await asyncio.sleep(1)
print("...World2!")

async def main():
await asyncio.gather(say_hello(), say_world())

if __name__ == "__main__":
asyncio.run(main())

"""
输出:
Hello...
...World!
Hello2...
...World2!
"""

并发运行多个任务

使用await asyncio.gather()。参考上面示例

超时控制

防止某个异步任务卡死导致整个程序挂起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import asyncio

async def long_running_task():
await asyncio.sleep(10)
print("测试")

async def main():
try:
await asyncio.wait_for(long_running_task(), timeout=2.0)
except asyncio.TimeoutError:
print("任务超时了!")

asyncio.run(main())

"""
输出:
任务超时了!
"""

异步任务分组与管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import asyncio

async def task(name):
print(f"name: {name}")

return name

async def main():
async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(task("xiaoli"))
task2 = tg.create_task(task("xiaowang"))

#退出with时,所有任务均已完成
print(f"结果:{task1.result()}, {task2.result()}")

asyncio.run(main())

"""
输出:
name: xiaoli
name: xiaowang
结果:xiaoli, xiaowang
"""

异步迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import asyncio

async def async_generator(name):
for i in range(3):
print(f"{name}-{i}: 开始")
await asyncio.sleep(0.5)
yield i
print(f"{name}-{i}: 结束")

async def consumer(name):
async for item in async_generator(name):
print(f"{name} - {item}")

async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(consumer("li"))
tg.create_task(consumer("wang"))

asyncio.run(main())

"""
输出:
li-0: 开始
wang-0: 开始
li - 0
li-0: 结束
li-1: 开始
wang - 0
wang-0: 结束
wang-1: 开始
li - 1
li-1: 结束
li-2: 开始
wang - 1
wang-1: 结束
wang-2: 开始
li - 2
li-2: 结束
wang - 2
wang-2: 结束
"""

异步上下文管理器

__aenter__ 和 __aexit__ 是异步上下文管理器的核心,它们必须配合 async with 语句才能生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import asyncio

class AsyncSession:
def __init__(self, name):
self.name = name

async def __aenter__(self):
print(f">>> {self.name}: 正在建立异步连接...")
await asyncio.sleep(0.5)
return self

async def __aexit__(self, exc_type, exc, tb):
print(f"<<< {self.name}: 正在关闭异步连接...")
await asyncio.sleep(0.5)

async def work(name):
async with AsyncSession(name) as session:
print(f"{name}:正在进行数据库查询操作...")
await asyncio.sleep(1)
print(f"{name}:操作完成。")

async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(work("li"))
tg.create_task(work("wang"))

asyncio.run(main())

"""
输出:
>>> li: 正在建立异步连接...
>>> wang: 正在建立异步连接...
li:正在进行数据库查询操作...
wang:正在进行数据库查询操作...
li:操作完成。
<<< li: 正在关闭异步连接...
wang:操作完成。
<<< wang: 正在关闭异步连接...
"""

处理阻塞代码

如果你必须在异步代码中调用同步的阻塞代码(如 requests.get() 或繁重的 CPU 计算),需要使用线程池来避免阻塞主循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import asyncio
import time
from concurrent.futures import ThreadPoolExecutor

def blocking_code(name):
time.sleep(3) #传统的阻塞同步代码
return f"{name}:同步数据"

async def work(name):
loop = asyncio.get_event_loop()

print(f"{name}:开始")
# 使用线程池运行阻塞代码
with ThreadPoolExecutor() as pool:
result = await loop.run_in_executor(pool, blocking_code, name)

print(result)

print(f"{name}:结束")

async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(work("Li"))
tg.create_task(work("Wang"))

asyncio.run(main())

"""
输出:
Li:开始
Wang:开始
Li:同步数据
Li:结束
Wang:同步数据
Wang:结束
"""

模块

在 Python 的设计哲学中,模块的概念非常简单且直接:文件即模块。只要一个文件以 .py 为后缀,它就是一个合法的 Python 模块,可以通过 import 语句被其他程序调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1. 导入模块
import math

2. 导入并重命名(别名)
import numpy as np

3. 直接将模块中的特定函数、类或变量引入当前命名空间
from math import sqrt, pi
导入并重命名成员
from math import sqrt as square_root
导入模块内所有内容
from math import *

4. 动态导入
在程序运行过程中,根据字符串动态决定导入哪个模块。这对于插件系统或根据配置加载模块非常有用。
import importlib

module_name = "math"
math_module = importlib.import_module(module_name)
print(math_module.sqrt(16))

5. 相对导入与绝对导入
绝对导入: 从项目根目录开始搜索。
from my_package.sub_module import my_function

相对导入: 使用 . 代表当前目录,.. 代表上级目录。
# 在 my_package/sub_module.py 中调用同级模块
from . import sibling_module
# 调用上级模块
from .. import parent_module

try

try 基础

1
2
3
4
try:
result = 10 / 0
except ZeroDivisionError: # 类似if 可以写多个except
print("不能除以0!")

使用 as 获取异常对象

1
2
3
4
5
6
7
8
9
try:
result = 10 / 0
except ZeroDivisionError as e: # 类似if 可以写多个except
print(f"不能除以0!: {e}")

"""
输出:
不能除以0!: division by zero
"""

else 子句

else 代码块只有在 try 块中没有发生任何异常时 才会执行。

1
2
3
4
5
6
7
8
9
10
11
try:
result = 10 / 2
except ZeroDivisionError as e: # 类似if 可以写多个except
print(f"不能除以0!: {e}")
else:
print(f"计算结果:{result}")

"""
输出:
计算结果:5.0
"""

finally 子句

finally 块无论是否发生异常都会执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try:
result = 10 / 0
except ZeroDivisionError as e: # 类似if 可以写多个except
print(f"不能除以0!: {e}")
else:
print(f"计算结果:{result}")
finally:
print(f"测试")

"""
输出:
不能除以0!: division by zero
测试
"""

使用 raise 主动抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try:
result = 10 / 2
raise ValueError("主动触发错误")
except ZeroDivisionError as e: # 类似if 可以写多个except
print(f"不能除以0!: {e}")
except ValueError as e:
print(f"捕获异常: {e}")
else:
print(f"计算结果:{result}")
finally:
print(f"测试")

"""
输出:
捕获异常: 主动触发错误
测试
"""

额外

语法糖切片,格式 object[start:stop:step]

支持类型:List, String, Tuple。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 基础写法
print(nums[1:4]) # [1, 2, 3]

# 省略写法
print(nums[:3]) # [0, 1, 2]
print(nums[7:]) # [7, 8, 9]
print(nums[:]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 步长控制
print(nums[1:8:2]) # [1, 3, 5, 7]
print(nums[::3]) # [0, 3, 6, 9]

# 负数索引
print(nums[-3:]) # [7, 8, 9]
print(nums[2:-2]) #[2, 3, 4, 5, 6, 7]

# 负数步长 (翻转)
print(nums[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(nums[8:2:-2]) # [8, 6, 4]

空语句pass

“代码占位符”,在没有确定函数,类,if,while等这些里面的具体写的代码。可以写个pass占着,让代码正常运行。

1
2
3
4
5
clss User:
pass

def printf():
pass

推导式

列表推导式

1
2
3
4
5
6
7
8
9
10
11
12
# 计算1到5的平方
squares = [x**2 for x in range(1, 6)] # [1, 4, 9, 16, 25]

# 获取1到10的偶数(if写for后面,过滤元素)
evens = [x for x in range(1, 11) if x % 2 == 0] # [2, 4, 6, 8, 10]

# 奇数都变为负数(if写for前面,根据条件对元素进行处理)
results = [x if x % 2 == 0 else -x for x in range(1, 6)] # [-1, 2, -3, 4, -5]

# 嵌套循环 将二维数值展开成一维
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [num for row in matrix for num in row] # [1, 2, 3, 4, 5, 6]

字典推导式

1
2
3
4
5
6
7
# 将名字列表转换为“名字:名字长度”的字典
names = ["Alice", "Bob", "Charlie"]
name_lengths = {name: len(name) for name in names} # {'Alice': 5, 'Bob': 3, 'Charlie': 7}

# 键值反转
old_dict = {'a': 1, 'b': 2, 'c': 3}
new_dict = {value: key for key, value in old_dict.items()} # {1: 'a', 2: 'b', 3: 'c'}

集合推导式

1
2
3
# 提取不重复的字母,并转换为大写
text = "hello world"
unique_chars = {char.upper() for char in text if char.isalpha()} # {'R', 'L', 'W', 'D', 'H', 'O', 'E'}

模拟元组推导式

1
2
3
4
5
# 以下写法并不会生成元组
gen = (x**0.5 for x in range(1, 10)) # <generator object <genexpr> at 0x00000190C70A35E0>

# 曲线救国
my_tuple = tuple(x for x in range(1, 5)) # (1, 2, 3, 4)

注意: 元组(Tuple)其实并没有专门的“元组推导式”

迭代器和生成器

最核心的优势是省内存(不需要一次性把所有数据加载到内存中),高效的处理大型数据集合。

生成器是一种特殊的迭代器。不需要手动去写 __iter__() 和 __next__() 方法,Python 帮你实现了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 迭代器
my_list = [1, 2, 3]
my_iterator = iter(my_list)
next(my_iterator) # 1
next(my_iterator) # 2
next(my_iterator) # 3
next(my_iterator) # 错误StopIteration

# 迭代器
class SimpleCounter:
def __init__(self, limit):
self.limit = limit
self.current = 1

# 定义这个方法,告诉编译器这个类可以迭代
def __iter__(self):
return self

def __next__(self):
if self.current <= self.limit:
result = self.current
self.current += 1
return result
else:
# 超出,抛出异常
raise StopIteration

counter = SimpleCounter(4)

print(f"next输出:",next(counter)) # next输出: 1

# for 会自动调用next()
for num in counter:
print(num) # 2, 3, 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 生成器
def countdown(n):
while n > 0:
yield n
n -= 1

"""
执行到 yield 时,函数会“暂停”并把值返回出去。下一次调用 next() 时,函数会从上次暂停的地方继续往下执行,而不是从头开始。
"""

counter = countdown(3)
next(counter) # 3
next(counter) # 2
next(counter) # 1
next(counter) # 错误StopIteration

# 生成器表达式(省内存!只有在你需要时才计算)
squares_gen = (x**2 for x in range(1000))
print(squares_gen) # <generator object <genexpr> at 0x00000190C718A4D0>

next(squares_gen) # 0
next(squares_gen) # 1

关键字with

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 读取文件 with执行玩后,会自动关闭文件
with open("score.txt", "r", encoding="utf-8") as file:
content = file.read()
print(f"文件内容:", content)


# 自定义with功能
from contextlib import contextmanager

@contextmanager
def log_block(title):
print(f"======【开始:{title}】======") # 相当于__enter__
try:
yield # 代码此处暂停,先去执行with内部代码
finally:
print(f"======【结束:{title}】======") # 相当于 __exit__

with log_block("查询信息"):
print("连接数据库...")
print("拿到用户数据!")

"""
输出:
======【开始:查询信息】======
连接数据库...
拿到用户数据!
======【结束:查询信息】======
"""

# 自定义with功能
class DatabaseConnection:
def __init__(self, db_url):
self.db_url = db_url
self.is_connected = False

# 建立连接
def __enter__(self):
print(f"连接数据库:{self.db_url}")
self.is_connected = False
return self

# 关闭连接
def __exit__(self, exc_type, exc_val, exc_tb):
self.is_connected = False
print("数据库连接以关闭")

# 异常处理
if exc_type:
print(f"警告:检测到内部报错 {exc_val} !")

return True

with DatabaseConnection("localhost:3306") as db:
print("写入用户消费记录")

# 模拟错误
raise ValueError("余额不足!")

"""
正常输出:
连接数据库:localhost:3306
写入用户消费记录
数据库连接以关闭

模拟错误输出:
连接数据库:localhost:3306
写入用户消费记录
数据库连接以关闭
警告:检测到内部报错 余额不足! !
"""

类型提示

: (冒号):用于变量、类属性以及函数参数的类型声明。

-> (箭头):专门用于声明函数的返回值类型。

示例:

1
2
def greet(name: str, age: int) -> str:
return f"Hello {name}, you are {age} years old."

python 基础
https://fu01.github.io/posts/98b77d55/
作者
Fu01
发布于
2026年5月22日
许可协议