一: cursor.execute
cursor.execute(sql, parameters)
- sql:字符串类型,要执行的 SQL 语句(如查询、插入、更新等)。
- parameters(可选):元组或字典,用于传递 SQL 语句中的参数(避免 SQL 注入,推荐使用)。
- 执行无参数的 SQL 语句
# 示例:查询所有图书
cursor.execute("SELECT * FROM books")
# 获取结果
all_books = cursor.fetchall() # 所有结果
- 执行带参数的 SQL 语句(推荐) 使用参数化查询(? 占位符)传递动态值,避免直接拼接字符串(防止 SQL 注入和语法错误)。
- 方式 1:使用 ? 作为占位符(SQLite 推荐)
- 参数以元组形式传递,顺序与 ? 一一对应。
# 示例:查询作者为"鲁迅"**的图书**
author = "鲁迅"
# SQL 中用?代替具体值
cursor.execute("SELECT * FROM books WHERE author = ?", (author,)) # 注意元组的逗号
# 获取结果
books = cursor.fetchall()
- 方式 2:使用命名占位符(如 :name)
- 参数以字典形式传递,可读性更好(适合参数较多的场景)。
# 示例:插入新图书
book_data = {
"title": "Python编程",
"author": "张三"
}
cursor.execute('''
INSERT INTO books (title, author)
VALUES (:title, :author)
''', book_data) # 字典的key与占位符:title、:author对应
conn.commit() # 提交事务(写操作必需)
- 方式3. 执行批量操作(executemany)
- 对多条数据执行相同的 SQL 语句(如批量插入),效率高于多次调用 execute。
# 示例:批量插入3本图书
books = [
("book1", "author1"),
("book2", "author2"),
("book3", "author3")
]
cursor.executemany(
"INSERT INTO books (title, author) VALUES (?, ?)",
books # 列表中的每个元组对应一条数据
)
conn.commit()
关键注意事项
-
写操作需要提交事务: 执行 INSERT/UPDATE/DELETE 等修改数据的操作后,必须调用 conn.commit() 才能将修改保存到数据库。若出错,可调用 conn.rollback() 回滚。
-
参数传递格式:
- 单参数时,元组需加逗号:(value,)(避免被解析为普通括号)。
- 字符串参数无需手动加单引号,参数化查询会自动处理。
- SQL 注入风险: 严禁直接拼接字符串生成 SQL(如 f"SELECT * FROM books WHERE author = '{author}'"),恶意输入(如 author = "'); DROP TABLE books;--)会导致数据泄露或破坏。
- 结果获取方法:
- cursor.fetchone():获取一条结果(查询时用)。
- cursor.fetchall():获取所有结果(查询时用)。
- cursor.rowcount:获取受影响的行数(如 UPDATE/DELETE 后)。
完整试例:
import sqlite3
# 连接数据库
conn = sqlite3.connect("test.db")
cursor = conn.cursor()
# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT,
age INTEGER
)
''')
# 插入数据(带参数)
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Alice", 25))
conn.commit() # 提交
# 查询数据
cursor.execute("SELECT * FROM users WHERE age > ?", (18,))
print(cursor.fetchall()) # 输出: [(1, 'Alice', 25)]
# 关闭连接
cursor.close()
conn.close()
二. title[:27] 这种表达什么意思?
-
title[:27] 是 Python 中的字符串切片操作,表示截取字符串 title 中从开头到第 26 个字符(共 27 个字符)的子串。
-
[:27] 是切片语法,含义是 “从索引 0 开始,到索引 26 结束(不包含索引 27)”。
# 若标题长度超过30,就截取前27个字符并加"..."
short_title = title[:27] + "..." if len(title) > 30 else title
例:
-
对于一个 40 字符的长标题: "深度学习入门:基于Python的理论与实现(全彩版)"
-
处理后会显示为: "深度学习入门:基于Python的理论与实..."
三. print(f"{'ID':<4} {'标题':<30} {'作者':<20} {'状态':<6} {'评分':<4} {'添加日期'}") 这个<是小于的意思吗
答案:错
- 这里的 < 不是 “小于” 的意思,而是 Python f-string 中的格式化符号,表示 “左对齐” 并指定宽度。
具体说明:
- {'ID':<4}:将字符串 "ID" 左对齐,总宽度占 4 个字符位置
- {'标题':<30}:将 “标题” 左对齐,总宽度占 30 个字符位置
- 以此类推,< 后的数字表示该列的固定宽度
ID 标题 作者 状态 评分 添加日期
--------------------------------------------------------------------------------
1 Python编程入门 张三 已读 5★ 2023-10-01
2 数据结构与算法 李四 未读 — 2023-10-02
填充字符(自定义对齐时的填充内容)
在对齐符号(</>/^)前可以指定填充字符(默认是空格),通常用于生成带边框或特殊样式的文本。 示例:
text = "Python"
print(f"左对齐填充*: {text:*<10}") # 输出:左对齐填充*: Python****
print(f"居中填充-: {text:-^10}") # 输出:居中填充-: --Python--
print(f"右对齐填充0: {text:0>10}") # 输出:右对齐填充0: 0000Python
四:处理字符空格
- strip() 移除字符串首尾的空白字符(包括空格、换行符 \n、制表符 \t 等)。
- lstrip():只移除开头的空白
- rstrip():只移除结尾的空白
五:def _connect_db(self) -> None: 这个->箭头代表什么意思?
- 类型注解的作用
- 提高代码可读性:一眼就能知道函数的返回值类型(或参数类型),不用通读函数逻辑。
- 例如:
def add(a: int, b: int) -> int:明确 “参数是整数,返回值也是整数”。
def get_name() -> str:明确 “返回值是字符串”。
六:dict(zip(columns, row)) 是什么意思?
dict(zip(columns, row)) 是 Python 中一种常用的将 “字段名列表” 与 “数据行” 组合成字典的方式,转换为 “键值对” 形式(字段名作为键,对应的值作为值)。
- zip(columns, row) 示例:
若 columns = ['id', 'name'],row = (1, '张三')
则 zip(columns, row) 会生成 [('id', 1), ('name', '张三')](简化理解,实际是迭代器)。
- dict(...)
dict() 函数可以将 “键值对组成的可迭代对象” 转换为字典。
示例:
将上面的 [('id', 1), ('name', '张三')] 传入 dict(),
会得到 {'id': 1, 'name': '张三'}
对比JS:dict(zip(columns, row)) VS Object.fromEntries()
JS要结合 Array.prototype.map() 或直接配合数组解构,核心都是将 “键数组” 和 “值数组” 对应组合成对象(类似 Python 的字典)。
- “zip” 配对(键值对应)
- Python 的 zip(columns, row) 会把 columns(键列表)和 row(值列表)的元素一一配对成 (键, 值) 元组。
- 在 JS 中,可以用 Array.prototype.map() 实现类似 “zip” 的效果:
const columns = ['id', 'title', 'status']; // 键数组(类似 Python 的 columns)
const row = [1, '完成报告', '已完成']; // 值数组(类似 Python 的 row)
// 手动“zip”:将 columns 和 row 的元素一一配对成 [键, 值] 数组
const zipped = columns.map((key, index) => [key, row[index]]);
// 结果:[ ['id', 1], ['title', '完成报告'], ['status', '已完成'] ]
- 转换为对象(类似 Python 的 dict)
- Python 的 dict(...) 将配对后的元组转换为字典;JavaScript 的 Object.fromEntries() 可以将 [ [键, 值], ... ] 形式的数组转换为对象:
//拿到上面的zipped
const taskObj = Object.fromEntries(zipped);
// 结果:{ id: 1, title: '完成报告', status: '已完成' }
完整案例:
// 模拟数据库查询的“字段名”和“数据行”
const columns = ['id', 'title', 'status'];
const row = [1, '完成报告', '已完成'];
// 组合成对象(对应 Python 的 dict(zip(columns, row)))
const taskObj = Object.fromEntries(
columns.map((key, index) => [key, row[index]])
);
console.log(taskObj);
// 输出:{ id: 1, title: '完成报告', status: '已完成' }
// 访问数据(类似 Python 的 task['title'])
console.log(taskObj.title); // 输出:'完成报告'
总结: Python 中 dict(zip(columns, row)) 的核心是 “键值配对→转字典”。 JavaScript 中对应的实现是 Object.fromEntries(columns.map((k,i)=>[k,row[i]]))(或配合手动 zip 函数),最终将 “键数组” 和 “值数组” 转换为对象,实现完全相同的效果。
七:def update_task(self, task_id: int, **kwargs) -> bool: **kwargs什么意思
函数定义中的 **kwargs 是 Python 的一种可变参数语法 ,用于接收任意数量的关键字参数(键值对形式),并将它们打包成一个字典(dict)。
-
具体含义: ** 是解包运算符,在这里用于 “收集” 所有未被显式定义的关键字参数。 kwargs 是参数名(可以自定义,但通常约定用 kwargs,全称是 "keyword arguments"),它会被自动转换为一个字典,键是参数名,值是对应的参数值。
-
作用与使用场景: 在 update_task 函数中,**kwargs 的作用是 ** 灵活接收需要更新的任务字段 **。因为更新任务时,用户可能只需要修改部分字段(如只改状态,或只改优先级 + 标题),而不需要传递所有字段。
表示例:
# 只更新状态
manager.update_task(1, status="已完成")
# 同时更新标题和优先级
manager.update_task(2, title="新标题", priority="高")
# 甚至可以动态生成参数
update_fields = {"status": "进行中", "due_date": "2023-12-31"}
manager.update_task(3, **update_fields) # 用**解包字典作为参数
与函数逻辑的结合: 在 update_task 函数中,**kwargs 配合后续逻辑实现了 “动态更新”:
# 过滤有效字段(只保留允许更新的字段)
valid_fields = ["title", "description", "due_date", "priority", "status"]
updates = {k: v for k, v in kwargs.items() if k in valid_fields}
if not updates:
print("没有有效字段")
return false
跟JS方法传对象params有点相似
JS例:
// 模拟任务数据
let tasks = [
{ id: 1, title: "完成报告", status: "未完成", priority: "中" },
{ id: 2, title: "准备会议", status: "进行中", priority: "高" }
];
/**
* 更新任务(类似Python的update_task函数)
* @param {number} taskId - 任务ID
* @param {Object} updates - 要更新的字段(键值对,类似**kwargs)
* @returns {boolean} - 是否更新成功
*/
function updateTask(taskId, updates) {
// 1. 查找任务
const task = tasks.find(t => t.id === taskId);
if (!task) {
console.log(`未找到ID为${taskId}的任务`);
return false;
}
// 2. 定义允许更新的字段(过滤无效字段)
const validFields = ["title", "status", "priority", "dueDate"];
// 3. 只更新有效字段(类似Python的字典推导式筛选)
Object.keys(updates).forEach(key => {
if (validFields.includes(key)) {
task[key] = updates[key]; // 更新字段值
}
});
console.log(`ID为${taskId}的任务已更新`);
return true;
}
// 使用示例(类似Python调用update_task时传递关键字参数)
updateTask(1, { status: "已完成" }); // 只更新状态
updateTask(2, { title: "准备周会", priority: "中" }); // 同时更新标题和优先级
// 动态生成更新字段(类似Python中**字典解包)
const dynamicUpdates = { dueDate: "2023-12-31", status: "进行中" };
updateTask(1, dynamicUpdates);
console.log("更新后的任务列表:", tasks);
ES6 解构赋值的进阶用法:
// 解构赋值写法(更直观地分离必选和可选参数)
function updateTask(taskId, { title, status, priority, dueDate } = {}) {
// 这里直接使用 title、status 等变量,未传递则为 undefined
const task = tasks.find(t => t.id === taskId);
if (!task) return false;
if (title !== undefined) task.title = title;
if (status !== undefined) task.status = status;
// ...其他字段处理
return true;
}
// 调用方式不变
updateTask(1, { status: "已完成" });
八:updates = {k: v for k, v in kwargs.items() if k in valid_fields} 这个写法代表什么意思,
从 kwargs 中筛选出 “键(字段名)在 valid_fields 列表中” 的键值对,组成一个新字典 updates。
def update_books(self, id, **kwargs):
"""
动态更新图书信息(除id外的任意字段)
:param id: 图书ID(必须指定,用于定位要更新的记录)
:param**kwargs: 要更新的字段键值对(如title="新标题", author="新作者")
"""
if not kwargs: # 检查是否有要更新的字段
print("更新失败:没有需要修改的字段")
return
# 1. 定义允许更新的字段(防止修改id等不允许的字段)
valid_fields = ["title", "author", "publisher", "publish_year", "category"]
# 筛选出有效字段(过滤掉不允许更新的字段)
updates = {k: v for k, v in kwargs.items() if k in valid_fields}
if not updates: # 检查是否有有效字段
print("更新失败:没有有效的更新字段(允许的字段:title, author, publisher等)")
return
# 2. 动态构建SET子句(如"title = ?, author = ?")
set_clause = ", ".join([f"{field} = ?" for field in updates.keys()])
# 构建完整SQL语句
sql = f"UPDATE books SET {set_clause} WHERE id = ?"
# 3. 准备参数(更新字段的值 + id)
params = list(updates.values()) + [id]
try:
self.cursor.execute(sql, params)
if self.cursor.rowcount == 0:
print(f"更新失败:未找到ID为 {id} 的图书")
return
self.conn.commit()
print(f"更新成功:ID为 {id} 的图书已修改字段:{list(updates.keys())}")
except sqlite3.Error as e:
self.conn.rollback()
print(f"更新失败:{e}")
1. kwargs.items()
- kwargs 是通过 **kwargs 接收的关键字参数字典(例如 {"title": "新标题", "author": "张三", "invalid_key": "值"})。
- items() 方法会返回字典中所有键值对的迭代器(例如 [("title", "新标题"), ("author", "张三"), ("invalid_key", "值")])。
2. for k, v in kwargs.items()
- 遍历 kwargs 中的每个键值对,k 代表键(字段名),v 代表对应的值。
3. if k in valid_fields
- 过滤条件:只保留 “键 k 存在于 valid_fields 列表中” 的键值对。
- 假设 valid_fields = ["title", "author", "publisher"],则下例中 k="title" 和 k="author" 会被保留,k="invalid_key" 会被过滤。
4. {k: v ...}
- {k: v ...} 是字典推导式的固定格式,k: v 明确了新字典中 “键 - 值” 的对应关系。
- 将过滤后的键值对 (k, v) 组成新字典 updates。
- 如果省略 : v,写成 {k for ...},就变成了集合推导式(生成集合):
# 集合推导式(只有键,没有值)
fields = {k for k, v in kwargs.items() if k in valid_fields}
# 结果:{"title", "author"} (这是集合,不是字典)
完整案例:
kwargs = {
"title": "新标题",
"author": "张三",
"invalid_key": "无效值", # 不在valid_fields中
"publish_year": 2023
}
valid_fields = ["title", "author", "publisher", "publish_year"]
执行字典推导式后:
updates = {k: v for k, v in kwargs.items() if k in valid_fields}
# 结果:
# {
# "title": "新标题",
# "author": "张三",
# "publish_year": 2023
# }
九: ", ".join([f"{field} = ?" for field in updates.keys()]) 是什么意思
动态生成 SQL 语句中的 SET 子句,用于批量指定需要更新的字段。它会根据 updates 字典中的键(字段名),生成类似 title = ?, author = ?, publisher = ? 的字符串,方便后续拼接完整的 UPDATE 语句。
# 动态构建SET子句(如"title = ?, author = ?")
set_clause = ", ".join([f"{field} = ?" for field in updates.keys()])
# 构建完整SQL语句
sql = f"UPDATE books SET {set_clause} WHERE id = ?"
- updates.keys() updates 是筛选后的字段字典(例如 {'title': '新标题', 'author': '张三'})。 keys() 返回['title', 'author']。
- 列表推导式 [f"{field} = ?" for field in updates.keys()] 遍历每个字段名 field,用 f-string 生成 字段名 = ? 的字符串。 以上例为例,会生成列表 ['title = ?', 'author = ?']。
- 这里的 ? 是 SQL 参数化查询的占位符,用于后续传入具体值(防止 SQL 注入)。 ", ".join(...)
- join() 方法将列表中的字符串用 , (逗号 + 空格)连接起来,形成一个完整的字符串。 以上例为例,最终生成 title = ?, author = ?。 例:
updates = {
'title': 'Python入门',
'author': '李四',
'publisher': '编程出版社'
}
执行代码后
# 列表推导式结果:
[f"{field} = ?" for field in updates.keys()]
# → ['title = ?', 'author = ?', 'publisher = ?']
# join后结果:
set_clause = ", ".join(...)
# → "title = ?, author = ?, publisher = ?"
最终用途:
sql = f"UPDATE books SET {set_clause} WHERE id = ?"
# → "UPDATE books SET title = ?, author = ?, publisher = ? WHERE id = ?"
Python vs Js的不同点,python是符合比如逗号,-等,","写在join前面。js是写在后端
# 列表拼接
words = ["Hello", "world", "Python"]
result = " ".join(words) # 用空格分隔
print(result) # 输出: "Hello world Python"
# 元组拼接
nums = ("1", "2", "3") # 注意元素必须是字符串
result = "-".join(nums)
print(result) # 输出: "1-2-3"
# 特殊用法:拼接字符串中的字符(字符串也是可迭代对象)
s = "abc"
result = "_".join(s)
print(result) # 输出: "a_b_c"
// 基本用法
const words = ["Hello", "world", "JavaScript"];
const result = words.join(" "); // 用空格分隔
console.log(result); // 输出: "Hello world JavaScript"
// 数字数组(自动转字符串)
const nums = [1, 2, 3];
const result2 = nums.join("-");
console.log(result2); // 输出: "1-2-3"
// 无分隔符(直接拼接)
const arr = ["a", "b", "c"];
console.log(arr.join("")); // 输出: "abc"
// 默认分隔符(逗号)
console.log(arr.join()); // 输出: "a,b,c"
十:params = list(updates.values()) + [id] 这句话什么意思
set_clause = ", ".join([f"{field} = ?" for field in updates.keys()])
# 构建完整SQL语句
sql = f"UPDATE books SET {set_clause} WHERE id = ?"
# 3. 准备参数(更新字段的值 + id)
params = list(updates.values()) + [id]
self.cursor.execute(sql, params)
- updates.values()
- updates 是筛选后的有效字段字典(例如 {'title': '新标题', 'author': '张三'})。
- values() 方法返回字典中所有的值(即要更新的新值),结果是一个可迭代对象,例如 dict_values(['新标题', '张三'])。
- list(updates.values())
- 将上述值转换为列表,例如 ['新标题', '张三'],方便后续拼接。
- +[id]
- 用 + 运算符将 “更新值列表” 与 “包含 ID 的列表 [id]” 拼接起来。
- 假设 id = 5,则拼接后结果为 ['新标题', '张三', 5]。
updates = {
'title': 'Python入门',
'author': '李四',
'publisher': '编程出版社'
}
执行后
# 步骤1-2:获取更新值列表
list(updates.values()) # → ['Python入门', '李四']
# 步骤3:拼接ID
params = list(updates.values()) + [id] # → ['Python入门', '李四', 3]
总结: params = list(updates.values()) + [id] 的核心作用是按顺序整合 “更新值” 和 “定位 ID”