最近在复习,整理了一些python的基础知识,理论都是我总结手写的,代码有些部分时AI生成的
命名规则:模块即py文件-小写+下划线,类名-大写驼峰命名,函数/变量-小写+下划线,常量-全大写+下划线,私有属性-前单下划线+小写+下划线,强私有-前双下划线+小写+下划线
数据类型:主要类型(int、float、complex、decimal);bool类型其实是int子类(True-1,False-0),被认为是False的数据---None、False、0、空序列('',\[\],set()),其它所有的值都视为True。
集合类型:list(存储有序集合,有序、可重复、可变),tuple(函数返回多值、字典键,可重复、不可变、有序),set(去重、集合运算,可变、不可重复、无序),dict(配置缓存、映射、键不可重复,可变、有序)
类型转换与类型检查:int()、float()、str()、bool()、list()、tuple()、set()、dict(),类型检查使用isintance()和type()
浅拷贝和深拷贝:copy.copy(),copy.deepcopy()
一 循环与迭代器
python中的for循环底层是迭代器实现的,迭代器很省内存,它不会将数据一下都导入内存中,会当下的循环引入此次计算的变量到内存中,python中所有的可以放入for循环中进行循环计算的对象都可以生成迭代器
普通的for循环都可以用for x in list 的格式实现,同时python也提供了多种控制流工具:生成器表达式(惰性求值,节省内存),itertools模块(高效迭代),functools函数
迭代器协议定义了两个方法:iter() 返回迭代器对象本身,next() 返回下一个值或在没有更多值时抛出 StopIteration
python
from itertools import chain, islice, groupby, product
from functools import reduce
# 生成器表达式 - 惰性求值,不占内存
# 对比列表推导式(立即创建整个列表)
sum_of_squares = sum(x**2 for x in range(1000000)) # 不会创建百万元素的列表
# itertools.chain - 串联多个迭代器
list_a = [1, 2, 3]
list_b = [4, 5, 6]
for item in chain(list_a, list_b):
print(item) # 1, 2, 3, 4, 5, 6
# itertools.islice - 惰性切片(不需要将整个序列加载到内存)
def read_large_file(filepath):
with open(filepath) as f:
# 只读取前 100 行,不加载整个文件
for line in islice(f, 100):
yield line.strip()
# itertools.groupby - 分组
data = [
{"dept": "Engineering", "name": "Alice"},
{"dept": "Marketing", "name": "Bob"},
{"dept": "Engineering", "name": "Charlie"},
]
# 注意:groupby 需要先排序
data.sort(key=lambda x: x["dept"])
for dept, members in groupby(data, key=lambda x: x["dept"]):
print(f"{dept}: {[m['name'] for m in members]}")
# 嵌套循环优化 - itertools.product 替代多层 for
# 不推荐
for x in range(3):
for y in range(3):
process(x, y)
# 推荐
for x, y in product(range(3), range(3)):
process(x, y)
在实际开发中也可以自定义迭代器
python
# 自定义迭代器
class CountDown:
# 倒计时迭代器
def __init__(self, start: int):
self.current = start
def __iter__(self):
return self
def __next__(self):
if self.current <= 0:
raise StopIteration
self.current -= 1
return self.current + 1
for num in CountDown(5):
print(num) # 5, 4, 3, 2, 1
二 函数
python中的函数没有用大括号去标识函数的开始与结束,而是用tab键空格,返回值在声明的时候用 -> 返回对象,函数的返回值是一个对象时可以像node一样去解构,得到多个返回的对象
函数可以赋值给其它变量,也可以嵌套定义,也有闭包的概念(函数包含了外层函数作用域的变量)
python
def rate_limiter(max_calls: int, period: float):
# 创建一个限流装饰器
import time
calls = []
def decorator(func):
def wrapper(*args, **kwargs):
now = time.time()
# 清除过期的调用记录
calls[:] = [t for t in calls if now - t < period]
if len(calls) >= max_calls:
raise Exception("Rate limit exceeded")
calls.append(now)
return func(*args, **kwargs)
return wrapper
return decorator
@rate_limiter(max_calls=100, period=60) # 每分钟最多 100 次
Lambda是匿名函数,只能包含单个表达式,递归函数调用自身,高阶函数是函数作为参数或返回函数的函数,python的内置函数有:map()、filter()、sorted()
python
# Lambda 最常用于排序的 key 参数
users = [
{"name": "Charlie", "age": 35},
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
]
users.sort(key=lambda u: u["age"]) # 按年龄排序
users.sort(key=lambda u: (u["age"], u["name"])) # 多字段排序
# map - 对每个元素应用函数
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers)) # [1, 4, 9, 16, 25]
# 更推荐用列表推导式
squared = [x**2 for x in numbers]
# filter - 过滤元素
evens = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
# 更推荐用列表推导式
evens = [x for x in numbers if x % 2 == 0]
# sorted - 自定义排序
words = ["banana", "Apple", "cherry"]
print(sorted(words, key=str.lower)) # ["Apple", "banana", "cherry"]
# functools.reduce - 累积计算
from functools import reduce
total = reduce(lambda a, b: a + b, numbers) # 15
# 更推荐使用 sum()
total = sum(numbers)
三 生成器函数与yield
生成器函数使用yeild而不是return产出值,调用生成器函数不会执行函数体而是返回一个生成器对象,每次调用next()来产出值,函数从上次yield的位置继续执行,直到遇到下一个yield或函数结束
python
# 服务端应用:流式 HTTP 响应
def generate_csv_stream(query):
# 生成 CSV 数据流,适用于大数据导出
yield "id,name,email\n" # 表头
for user in PaginatedQuery(query):
yield f"{user.id},{user.name},{user.email}\n"
# Flask 中使用
@app.route("/export/users.csv")
def export_users():
return Response(
generate_csv_stream("SELECT * FROM users"),
mimetype="text/csv",
headers={"Content-Disposition": "attachment; filename=users.csv"}
)
四 控制流
python使用if/elif/else进行条件判断,条件表达式的值会被转换成bool值,这里有点类似js有隐式类型转换,python支持链式比较(如:a<b<c),三元表达式与js中的不同:status = "adult" if age >= 18 else "minor",这句是 如果age大于18则status为adult,否则为minor
python中没有switch,有相似的控制结构模式匹配,比如:
python
# match-case(Python 3.10+)
def handle_status(status_code: int) -> str:
match status_code:
case 200:
return "OK"
case 404:
return "Not Found"
case 500 | 502 | 503:
return "Server Error"
case code if code < 400:
return f"Client redirect: {code}"
case _:
return f"Unknown: {status_code}"
python中模式匹配有个高级用法---解构:
python
# 模式匹配的高级用法 - 解构
def process_command(command: str):
match command.split():
case ["quit"]:
print("Goodbye!")
case ["get", key]:
return cache.get(key)
case ["set", key, value]:
cache.set(key, value)
case ["delete", key] if key.startswith("temp_"):
cache.delete(key)
case _:
print("Unknown command")
while循环也是break跳出,内部常与try、except联用,比如:
python
# while 循环
retry_count = 0
while retry_count < 3:
try:
result = connect_to_db()
break
except ConnectionError:
retry_count += 1
time.sleep(2 ** retry_count) # 指数退避
else:
# while...else: 循环正常结束(没有 break)时执行
print("连接失败,已达最大重试次数")
五 面向对象编程(OOP)
python中一切皆对象这一点很像js,类是对象的蓝图。
使用class关键字定义类,__init__方法是构造函数,self参数代表实例本身,python支持实例属性、类属性、实例方法、类方法(@classmethod)、静态方法(@staticmethod)
python
Python 中一切皆对象,类是对象的蓝图。使用 class 关键字定义类。__init__
方法是构造函数(初始化方法),self 参数代表实例本身。Python 支持实例属性、类属性、
实例方法、类方法(@classmethod)和静态方法(@staticmethod)。
类与对象
class User:
# 用户类
# 类属性 - 所有实例共享
default_role = "user"
_count = 0 # 用于统计实例数量
def __init__(self, name: str, email: str, role: str = None):
# 实例属性 - 每个实例独立
self.name = name
self.email = email
self.role = role or self.default_role
self._password_hash = None # 私有属性
User._count += 1
# 实例方法
def get_display_name(self) -> str:
return f"{self.name} ({self.role})"
# 类方法 - 第一个参数是类本身
@classmethod
def get_count(cls) -> int:
return cls._count
@classmethod
def from_dict(cls, data: dict) -> "User":
# 工厂方法:从字典创建用户
return cls(
name=data["name"],
email=data["email"],
role=data.get("role"),
)
# 静态方法 - 不需要类或实例参数
@staticmethod
def validate_email(email: str) -> bool:
import re
pattern = r"^[\w.+-]+@[\w-]+\.[\w.]+$"
return bool(re.match(pattern, email))
# 魔术方法
Python 服务端开发学习工程 | 第 3 页
def __repr__(self) -> str:
return f"User(name={self.name!r}, email={self.email!r})"
def __str__(self) -> str:
return self.get_display_name()
def __eq__(self, other) -> bool:
if not isinstance(other, User):
return NotImplemented
return self.email == other.email
def __hash__(self) -> int:
return hash(self.email)
# 使用
user = User("Alice", "alice@example.com")
print(user) # Alice (user)
print(repr(user)) # User(name='Alice', email='alice@example.com')
print(User.get_count()) # 1
print(User.validate_email("test@example.com")) # True
# 工厂方法
user2 = User.from_dict({"name": "Bob", "email": "bob@example.com"})
python中的类支持继承(单继承、多继承)与方法重写,使用super()调用父类方法,方法重写允许子类提供父类方法的不同实现,python是遵循MRO(Method Relation Order,方法解析顺序)来决定多继承时方法的解析顺序
下面的例子中可以看到,优先使用组合(composition)而非继承。继承应该表示 'is-a' 关系,组合表示 'has-a' 关系。
python
# 多继承
class Serializable:
def serialize(self) -> str:
import json
return json.dumps(self.to_dict())
class Loggable:
Python 服务端开发学习工程 | 第 5 页
def log(self, action: str):
print(f"[{self.__class__.__name__}] {action}")
class AdminUser(Admin, Serializable, Loggable):
# 管理员用户,支持序列化和日志
pass
admin = AdminUser(
name="SuperAdmin", email="admin@example.com",
permissions=["read", "write", "delete"]
)
print(admin.serialize())
admin.log("created new user")
# 查看 MRO
print(AdminUser.__mro__)
# (<class 'AdminUser'>, <class 'Admin'>, <class 'User'>,
# <class 'BaseModel'>, <class 'Serializable'>, <class 'Loggable'>, ...)
python中的类支持封装、多态与抽象,
封装:通过命名约束控制属性的访问级别,单下划线(_arr)表示'私有'(约定、不强制),双下划线前缀(__arr)触发名称修饰(name, mangling),提供更强的封装
多态:不同类的对象可以对同一方法调用做出不同的响应,python的多态基于鸭子类型(duck typing)---不关心对象的类型,只关系对象是否有相应的方法
抽象:使用abc模块定义抽象基类(ABC),强制子类实现特定方法
python
from abc import ABC, abstractmethod
class Animal(ABC):
def __init__(self, name):
self.__name = name # 私有变量(名称改写为 _Animal__name)
@property
def name(self): # 只读访问
return self.__name
@abstractmethod
def speak(self): # 抽象方法,子类必须实现
...
class Dog(Animal):
def speak(self):
return f"{self.name}: 汪汪"
class Cat(Animal):
def speak(self):
return f"{self.name}: 喵喵"
# 多态:同一接口,不同行为
for a in (Dog("旺财"), Cat("咪咪")):
print(a.speak())
# Animal("x") 会报错:TypeError: Can't instantiate abstract class
# print(Dog("x").name) -> 可读
# Dog("x").__name -> AttributeError(私有变量外部不可直接访问)