Python用法记录

580 阅读13分钟

一: cursor.execute

cursor.execute(sql, parameters)
  • sql:字符串类型,要执行的 SQL 语句(如查询、插入、更新等)。
  • parameters(可选):元组或字典,用于传递 SQL 语句中的参数(避免 SQL 注入,推荐使用)。
  1. 执行无参数的 SQL 语句
# 示例:查询所有图书
cursor.execute("SELECT * FROM books")
# 获取结果
all_books = cursor.fetchall()  # 所有结果
  1. 执行带参数的 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()

关键注意事项

  1. 写操作需要提交事务: 执行 INSERT/UPDATE/DELETE 等修改数据的操作后,必须调用 conn.commit() 才能将修改保存到数据库。若出错,可调用 conn.rollback() 回滚。

  2. 参数传递格式:

  • 单参数时,元组需加逗号:(value,)(避免被解析为普通括号)。
  • 字符串参数无需手动加单引号,参数化查询会自动处理。
  • SQL 注入风险: 严禁直接拼接字符串生成 SQL(如 f"SELECT * FROM books WHERE author = '{author}'"),恶意输入(如 author = "'); DROP TABLE books;--)会导致数据泄露或破坏。
  1. 结果获取方法:
  • 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编程入门           张三                 已读     52023-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” 配对(键值对应)
  1. Python 的 zip(columns, row) 会把 columns(键列表)和 row(值列表)的元素一一配对成 (键, 值) 元组。
  2. 在 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)
  1. 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)
  1. updates.values()
  • updates 是筛选后的有效字段字典(例如 {'title': '新标题', 'author': '张三'})。
  • values() 方法返回字典中所有的值(即要更新的新值),结果是一个可迭代对象,例如 dict_values(['新标题', '张三'])。
  1. list(updates.values())
  • 将上述值转换为列表,例如 ['新标题', '张三'],方便后续拼接。
  1. +[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”