Day08 · 字符串(二)

Day08 · 字符串(二)

阶段:阶段一 · 核心基础 | 前置:Day07 | 技术基准:Python 3.15.0

学习目标

  • 掌握三种字符串格式化方式:% 运算符、str.format()、f-string(重点推荐)
  • 理解对齐、填充、精度等格式控制
  • 弄清编码与解码:Unicode、UTF-8、encode()/decode(),以及乱码的成因
  • 熟练使用字符串常用方法:find/index/count/replace/split/join/strip/lower/upper/startswith/endswith 等
  • 对比五种字符串拼接方法,知道场景该用哪个
  • 了解 f-string 在 3.12(PEP 701)后的七项现代写法,以及 3.15 新增的模板字符串 t-string(PEP 750)在 SQL/HTML 安全拼接中的思路

一、字符串格式化

把变量填进一段模板里,叫格式化。Python 有三代写法,越往后越推荐。

1.1、% 运算符(老式,C 语言风格)

类似 C 语言 printf:"模板" % (值1, 值2)。

格式符 含义
%s 字符串
%d 整数
%f 浮点数
%.2f 保留 2 位小数
%x 十六进制
%% 输出一个百分号
python 复制代码
# Author: XiaoJia
name = "小嘉"
age = 18
print("姓名:%s,年龄:%d" % (name, age))   # 姓名:小嘉,年龄:18
print("圆周率:%.2f" % 3.14159)             # 圆周率:3.14
print("百分号:100%%")                        # 百分号:100%
print("%-10s|" % "left")                     # 左对齐占 10 位
print("%10s|" % "right")                     # 右对齐占 10 位

% 是历史写法,新项目不推荐,但读旧代码会遇到。面试或维护老项目时看到 "%s" % name,要能立刻认出它等价于 f-string 的 f"{name}"。

1.2、str.format()(第二代)

用 {} 占位,.format(值) 填充:

python 复制代码
print("姓名:{},年龄:{}".format("小嘉", 18))
# 姓名:小嘉,年龄:18

print("{name} 正在学习 {lang}".format(name="小嘉", lang="Python"))
# 小嘉 正在学习 Python

print("{0} 学习 {1},{0}".format("小嘉", "Python"))
# 小嘉 学习 Python,小嘉

format 还支持对齐、精度、千分位:

python 复制代码
print("{:>10}|".format("右对齐"))     # 右对齐(占 10 位)
print("{:<10}|".format("左对齐"))     # 左对齐
print("{:^10}|".format("居中"))       # 居中
print("{:.2f}".format(3.14159))      # 3.14
print("{:,}".format(1234567))         # 1,234,567

1.3、f-string(第三代,强烈推荐)

Python 3.6+ 引入,在字符串前加 f,直接在 {} 里写变量甚至表达式,最简洁、最快、最好读。

python 复制代码
name = "小嘉"
age = 18
print(f"姓名:{name},年龄:{age}")        # 姓名:小嘉,年龄:18
print(f"明年 {age + 1} 岁")                # 明年 19 岁
print(f"圆周率:{3.14159:.2f}")           # 圆周率:3.14

# 对齐与填充
print(f"{'居中':^10}|")                    # 居中(^)
print(f"{1234567:,}")                      # 1,234,567

# 3.12+ f-string 还支持 = 调试写法
print(f"{age=}, {name=}")                 # age=18, name='小嘉'

小嘉结论:日常一律用 f-string ,% 和 .format() 能看懂即可。本课程后面的示例也以 f-string 为主。

1.4、f-string 现代能力(3.12+ 演进,Python 3.15 实测)

f-string 不是一成不变的。它 3.6 出生时只是"把变量塞进花括号";3.8 加了 = 调试语法;3.12 通过 PEP 701 对 f-string 的解析器做了一次全面重写,放开了一批老版本下会直接 SyntaxError 的写法。下面七项全部在本机 Python 3.15.0 实测通过------你在旧教程里看到的"f-string 不能嵌套同款引号"之类说法,3.12 之后已经过时。

① 嵌套同款引号:老规定是"f-string 外层用双引号,内层表达式就只能用单引号",反之亦然。3.12 后内外层可以用同款引号,解释器能正确配对。

python 复制代码
# Author: XiaoJia
name = "小嘉"
print(f"外层{f"内层{name}"}")
# 输出:外层内层小嘉

② 表达式内允许反斜杠 :老版本在 {} 里写 '\n' 会 SyntaxError,因为反斜杠在 f-string 字面量里是非法的;3.12 后表达式区可以自由写转义符。

python 复制代码
print(f"换行符:{'\n'!r}")
# 输出:换行符:'\n'

③ 字典键直写 :老版本里 f"{d['k']}" 这种"外层双引号、键用单引号"是允许的,但只要引号冲突就得先把字典项取到变量里。3.12 后任意引号组合都能直写,可读性更好。

python 复制代码
user = {"name": "小嘉", "age": 18}
print(f"姓名:{user['name']},年龄:{user['age']}")
# 输出:姓名:小嘉,年龄:18

④ 表达式内可写注释 :{} 里的表达式现在允许用 # 写行内注释(注意注释必须在花括号内部)。

python 复制代码
x = 10
print(f"结果 = {x + 5  # 加 5
}")
# 输出:结果 = 15

⑤ 多行表达式:花括号里的表达式可以跨行写,适合放较长的推导或函数调用。

python 复制代码
print(f"求和 = {(
    1 + 2 +
    3 + 4
)}")
# 输出:求和 = 10

⑥ 调试语法 f"{x=}" 增强 :3.8 引入,会把"变量名=值"一起打出来,调试时极好用;3.12 后 = 两侧留白也会原样保留在输出里。

python 复制代码
age = 18
city = "福州"
print(f"{age=}, {city=}")
# 输出:age=18, city='福州'

⑦ 动态格式宽度(嵌套格式说明符) :{x:{width}} 里的 width 本身可以是变量,实现"宽度由数据决定"的对齐。

python 复制代码
width = 10
word = "小嘉"
print(f"[{word:>{width}}]")   # 右对齐,宽 10
print(f"[{word:^{width}}]")   # 居中,宽 10
# 输出:
# [        小嘉]
# [    小嘉    ]

版本演进脉络:

版本 里程碑
3.6 PEP 498 引入 f-string,基础插值
3.8 增加 = 调试语法、= 后空格保留
3.12 PEP 701 全面重写解析器,放开上述七项写法
3.15 本机基准,七项全部可用

小嘉提醒:新能力是"放开限制",不是"鼓励乱用"。两个坑要记牢------第一,绝不要用 f-string 拼接用户输入去构造 SQL ,例如 f"SELECT * FROM users WHERE name = '{user}'",用户只要输入 ' OR 1=1 -- 就被注入了;正确做法是用数据库驱动的参数化查询(Day34 数据库章节会细讲)。第二,嵌套格式说明符 {x:{w}} 里的引号要和外层错开,否则虽然 3.12 后能编译,读起来还是费劲,关键处建议先把宽度存成变量再传入。

1.5、模板字符串 t-string(PEP 750,Python 3.15)------安全拼接进阶

f-string 的本质是"构造时立刻把插值算好、拼成一段纯文本 "。这在打日志时很爽,但在拼 SQL、拼 HTML 这类"需要把字面文本和插值位置分开处理"的场景里反而危险------用户输入和字面文本混在一起,就容易出 SQL 注入、XSS。PEP 750 在 Python 3.15 引入了模板字符串字面量 t"..." ,它构造出来的不是一段拼好的文本,而是一个保留"字面片段 + 插值位置"结构的 string.templatelib.Template 对象。

python 复制代码
# Author: XiaoJia
name = "世界"
t = t"hello {name}, sum={1 + 2}"
print(type(t).__name__)
# 输出:Template

print(str(t))
# 输出:Template(strings=('hello ', ', sum=', ''), interpolations=(Interpolation('世界', 'name', None, ''), Interpolation(3, '1 + 2', None, '')))

注意 str(t) 出来的不是拼接好的 "hello 世界, sum=3" ,而是一个描述结构的 repr:strings 是三段字面文本,interpolations 是两个插值点。这就是 t-string 和 f-string 最核心的区别------f-string 一构造就把结构抹平成纯文本,t-string 把结构留给你自己处理。

f-string vs t-string 对比:

维度 f"..." t"..."
构造结果 拼好的 str string.templatelib.Template 对象
表达式求值 构造时立即求值、立即拼进文本 构造时立即求值 (非惰性),但只存进 Interpolation.value,不拼成文本
str(t)/format(t) 就是拼好的字符串 返回结构 repr,不是拼接文本
字面与插值关系 已混合,不可分离 通过 __iter__ 交替吐出,可分离
典型用途 日志、UI、日常插值 SQL 参数化、HTML 转义等安全拼接

Template 的迭代协议 :直接 for piece in t,它会交替 吐出字面文本(str)和插值点(Interpolation),这正是自写渲染器的抓手。

python 复制代码
for piece in t:
    print(type(piece).__name__, "->", repr(piece))
# 输出:
# str -> 'hello '
# Interpolation -> Interpolation('世界', 'name', None, '')
# str -> ', sum='
# Interpolation -> Interpolation(3, '1 + 2', None, '')

每个 Interpolation 在本机 3.15.0 上暴露四个属性:.value(已求值的值)、.expression(源码字符串)、.conversion(!r/!s/!a,无则 None)、.format_spec(格式说明符,无则空串)。注意 :它本身不带 convert()/format() 方法------转换与格式化由你的渲染器调用内置 repr()/str()/ascii() 与 format(value, spec) 完成,这正是 t-string"把渲染策略交给你"的设计哲学。

自写一个最小渲染器:把 Template 拼回普通字符串,体会"结构在手"的感觉。

python 复制代码
import html

def apply_conv(v, conv):
    if conv == 'r':
        return repr(v)
    if conv == 's':
        return str(v)
    if conv == 'a':
        return ascii(v)
    return str(v)

def render(tpl):
    out = []
    for piece in tpl:
        if isinstance(piece, str):
            out.append(piece)                       # 字面片段,原样保留
        else:                                       # Interpolation
            if piece.conversion:                    # !r / !s / !a
                out.append(apply_conv(piece.value, piece.conversion))
            elif piece.format_spec:                 # 格式说明符作用于原始值
                out.append(format(piece.value, piece.format_spec))
            else:
                out.append(str(piece.value))
    return "".join(out)

print(render(t))
# 输出:hello 世界, sum=3

# 格式说明符与 conversion 在 t-string 里同样生效
print(render(t"pi={3.14159:.2f}"))
# 输出:pi=3.14
print(render(t"str={'hi'!r}"))
# 输出:str='hi'

安全用例一:render_sql------把插值换成占位符,防 SQL 注入 。字面 SQL 原样保留,所有用户输入的位置统一换成 %s,参数收集成 tuple 交给数据库驱动去绑定------这样用户输入永远不会拼进 SQL 文本本身。

python 复制代码
def render_sql(tpl):
    """把 t-string 渲染成 (SQL 文本, 参数 tuple)。
    字面文本原样保留,插值位置换成 %s,参数收集到 tuple。"""
    parts, params = [], []
    for piece in tpl:
        if isinstance(piece, str):
            parts.append(piece)
        else:
            parts.append("%s")
            params.append(piece.value)
    return "".join(parts), tuple(params)

user_input = "Alice'; DROP TABLE users;--"
age = 18
sql_t = t"SELECT * FROM users WHERE name = '{user_input}' AND age > {age}"
sql_text, args = render_sql(sql_t)
print(sql_text)
# 输出:SELECT * FROM users WHERE name = '%s' AND age > %s
print(args)
# 输出:("Alice'; DROP TABLE users;--", 18)

看到没有:恶意字符串 Alice'; DROP TABLE users;-- 没有被拼进 SQL 文本,而是乖乖待在参数 tuple 里,由数据库驱动在绑定时转义。这就是参数化查询防注入的本质,Day34 讲数据库时会反复用到这个思路。

安全用例二:render_html------用 html.escape 转义,防 XSS 。用户昵称这类输入要原样插进 HTML 时,必须先转义 < > & ' ",否则一段 <script> 就能在别人浏览器里执行。

python 复制代码
def render_html(tpl):
    out = []
    for piece in tpl:
        if isinstance(piece, str):
            out.append(piece)
        else:
            out.append(html.escape(str(piece.value)))   # 插值一律转义
    return "".join(out)

nick = "<script>alert('xss')</script>"
page = t"<div>欢迎,{nick}</div>"
print(render_html(page))
# 输出:<div>欢迎,&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;</div>

<script> 被转义成 &lt;script&gt;,浏览器只会把它当文本显示,不会执行。这就是 Day42 Web 章节里"模板自动转义"的原理。

一个常见误解澄清:t-string 不是惰性求值 。有同学以为 t"..." 会把表达式拖到渲染时才算,实测并非如此------构造 Template 时表达式就已经求值,结果存在 Interpolation.value 里了。

python 复制代码
seen = []
def track():
    seen.append("eval'd")
    return 999

t3 = t"v={track()}"
print(seen)        # 构造完 Template,seen 已经非空
# 输出:["eval'd"]

t-string 的价值不在于"懒",而在于**"保留结构、不拼文本"**------让你能写一个对所有插值点统一做安全处理的渲染器,而不是把安全逻辑散落在每一次拼接里。

小嘉提醒:t-string 是 3.15 才落地的新特性,生态还没铺开,日常打日志、拼 UI 继续用 f-string 就好;它真正的主场是后面 Day34 数据库参数化、Day42 Web 模板转义这类"安全拼接"场景。今天先建立概念:凡是要把用户输入插进 SQL/HTML,别用 f-string 直接拼,要么用驱动自带的参数化,要么用 t-string + 自写渲染器统一转义。

二、编码与解码

2.1、为什么会有乱码

计算机只认数字。文字要存进计算机,就得给每个字符编个号,这套编号规则叫编码。常见编码:

  • ASCII:只含英文字母和符号,128 个字符。
  • Unicode:给世界上每个字符(含中文)一个唯一编号(码点)。
  • UTF-8:Unicode 的一种存储实现,变长编码,英文字符占 1 字节、中文通常占 3 字节,是目前互联网最通用的编码。
  • GBK:中文 Windows 本地编码,只兼容中英文。

乱码的本质:用 A 编码存的文字,用 B 编码去读,对不上号就花了。

2.2、str 与 bytes 的转换

Python 3 中:文本是 str(Unicode),二进制是 bytes。二者通过 encode()(编码)和 decode()(解码)互转。

python 复制代码
# Author: XiaoJia
s = "你好"
b = s.encode("utf-8")       # str → bytes(编码)
print(b)                    # b'\xe4\xbd\xa0\xe5\xa5\xbd'
print(type(b))              # <class 'bytes'>

s2 = b.decode("utf-8")      # bytes → str(解码)
print(s2)                   # 你好

# 指定编码,GBK 对比
print("你好".encode("gbk"))  # b'\xc4\xe3\xba\xc3'  字节数与 utf-8 不同
python 复制代码
# 常见坑:编码解码不一致 → 乱码或报错
raw = "你好".encode("utf-8")
# print(raw.decode("gbk"))   # 乱码(不同字节表)
print(raw.decode("utf-8"))    # 你好   编码解码用同一种就对

规则:存文件、网络传输用 bytes(指定编码 utf-8);读出来用同一种编码 decode() 回 str。前后一致,永不乱码。

2.3、乱码是怎么产生的:一个完整案例

举个最常见的场景:你在 Windows 记事本里保存了一个中文文件,默认编码是 GBK,然后用 Python 按 UTF-8 去读,就乱了。

python 复制代码
# 假设文件实际是 GBK 编码保存的
# wrong = open("note.txt", encoding="utf-8").read()   # 乱码或 UnicodeDecodeError
# right = open("note.txt", encoding="gbk").read()     # 用对编码就正常

排查口诀:先确认"这串字节是用什么编码写的",再用同一个编码去读。中文 Windows 老文件多为 GBK,Linux/Web 多为 UTF-8;不确定时,UTF-8 优先试,失败再试 GBK。

编码 英文占字节 中文占字节 典型场景
ASCII 1 不支持 早期英文系统
UTF-8 1 3 现代互联网、Python 3 默认
GBK 1 2 中文 Windows 老文件
Unicode 2~4 2~4 内存中字符的统一编号

三、字符串常用方法

字符串方法极多,下面是最高频的一批(都返回新串,不改原串)。

3.1、查找与统计

python 复制代码
s = "hello python"
print(s.find("python"))      # 6    找到返回起始下标
print(s.find("java"))        # -1   找不到返回 -1(不报错)
print(s.index("python"))      # 6    类似 find,但找不到会报 ValueError
print(s.count("o"))           # 2    统计 "o" 出现次数

3.2、大小写与填充

python 复制代码
s = "Hello Python"
print(s.upper())             # HELLO PYTHON
print(s.lower())             # hello python
print(s.title())             # Hello Python
print(s.capitalize())        # Hello python   仅首字母大写
print("abc".center(10, "*")) # ***abc****    居中填充
print("7".zfill(3))          # 007           左侧补零到 3 位

3.3、拆分与连接

python 复制代码
# split 拆分:字符串 → 列表
print("2024-05-20".split("-"))        # ['2024', '05', '20']
print("a,b,c,d".split(",", 2))        # ['a', 'b', 'c,d']  最多拆 2 次
print("hello world".split())          # ['hello', 'world']  默认按空白

# join 连接:可迭代对象 → 字符串
print("-".join(["2024", "05", "20"])) # 2024-05-20
print("".join(["Hello", " ", "World"]))# Hello World
print(",".join(str(i) for i in range(1, 6)))  # 1,2,3,4,5

3.4、替换

python 复制代码
s = "hello world"
print(s.replace("world", "python"))   # hello python
print(s.replace("l", "L"))            # heLLo worLd   全替换
print(s.replace("l", "L", 1))          # heLlo world   只替换前 1 个

3.5、去空白与判断

python 复制代码
s = "   hello python   "
print("[" + s.strip() + "]")           # [hello python]   去两端空白
print("[" + s.lstrip() + "]")          # 去左端
print("[" + s.rstrip() + "]")          # 去右端
print("###abc###".strip("#"))          # abc   可指定去除字符

# 判断类(返回 bool)
print("python.py".endswith(".py"))     # True
print("README".startswith("RE"))       # True
print("abc".isalpha())                 # True   是否全字母
print("123".isdigit())                 # True   是否全数字
print(" ".isspace())                    # True

strip() 的实战意义:用户从键盘输入时常多打空格,input("姓名:").strip() 是标配(Day10 讲 input)。注意它只去两端,中间的空格不动------"a b c".strip() 还是 "a b c"。

3.6、综合实战:清洗一段脏数据

把零散学到的方法组合起来,处理一条真实感很强的"脏"用户输入:

python 复制代码
# Author: XiaoJia
raw = "  2024-05-20  14:30  "

# 1. 先去掉首尾空白
raw = raw.strip()
# 2. 按空白拆成两段(split 默认按任意空白,中间多个空格也能拆)
date_part, time_part = raw.split()
# 3. 把日期里的横杠换成点
date_part = date_part.replace("-", ".")
# 4. 判断是否以 2024 开头
print(date_part.startswith("2024"))     # True
# 5. 拼回一句完整描述
print(f"日期 {date_part},时间 {time_part}")

输出:

text 复制代码
True
日期 2024.05.20,时间 14:30

这一个小例子用到了 strip、split、replace、startswith、f-string 五个方法。真实项目里的数据清洗(Day41 数据分析实战)就是这类操作的放大版。

四、五种字符串拼接方法对比

方法 写法 适用场景 评价
+ a + b 少量、简单拼接 直观,但每次都造新串,循环里低效
str.join(列表) "".join(parts) 把列表/大量片段拼成一个串 性能最好,批量拼接首选
% "%s" % x 老式格式化 可读性一般,旧代码维护
str.format() "{}".format(x) 中等格式化 比 % 灵活
f-string f"{x}" 日常插值 最推荐,简洁高效
python 复制代码
# 对比:循环里拼接,+ vs join
parts = []
for i in range(5):
    parts.append(f"第{i+1}项")
result = "|".join(parts)       # 推荐:先收集到列表,最后一次 join
print(result)                  # 第1项|第2项|第3项|第4项|第5项

# 不要这样做(循环里反复 +,会产生大量中间串):
# s = ""
# for i in range(1000):
#     s += str(i)

五、本章边界与回顾

Day08 把字符串从"会定义、会切片"推进到"会格式化、会编码、会加工"。至此你已经掌握字符串的全部日常操作:需要填变量用 f-string,需要清洗文本用 strip/split/replace,需要拼批量结果用 join,遇到乱码先查编码。

和 Day07 一样,所有方法都不改动原串、返回新串。这一点贯穿字符串始终,请在脑子里立成铁律。下一课 Day09 我们回到运算的通用规则------运算符与表达式。

六、小结与边界回顾

Day08 是字符串的"应用篇":格式化让变量优雅地进模板,编码解码让中文不再乱码,几十个方法让清洗文本变成拼图游戏。学完这两天,你已经能处理现实世界里绝大多数字符串任务------登录页的用户名清洗、报表里的日期拼接、日志里的字段提取,思路都一样。在格式化这条线上,你还看到了 f-string 在 3.12(PEP 701)后的七项现代写法,以及 3.15 新增的 t-string(PEP 750)------后者为后面 Day34 数据库参数化、Day42 Web 模板转义这类安全拼接场景打下概念基础。

记住三句话:日常插值用 f-string;批量拼接先收集列表再 join;遇到乱码先核对编码是否前后一致。下一课进入运算符与表达式,把今天零散的计算串成完整逻辑。

练习题

  1. 用三种方式格式化同一句话"姓名:小嘉,年龄:18":分别用 %、.format()、f-string。
  2. 把 "圆周率是3.14159" 里的数字保留两位小数输出;再把数字 1234567 加千分位逗号。
  3. 写代码:"你好" 用 UTF-8 编码成 bytes,再用 GBK 解码会出现什么?用 UTF-8 解码又得到什么?为什么?
  4. 给定 "a,b,,c,d,",用 split(",") 拆成列表,再用 "-".join() 拼回去,观察空字符串元素的影响。
  5. 用户输入 " 小嘉 ",用 strip() 处理后判断它是否等于 "小嘉",体会为什么输入框一定要 strip。
  6. 思考题:为什么循环里拼接字符串推荐先 append 到列表再 join,而不是直接 +=?(提示:字符串不可变)
  7. (3.12+ 新写法)在本机 Python 3.15 上,依次写出下列 f-string 并运行验证:① 外层双引号、内层也用双引号嵌套的 f-string;② {x=} 调试语法同时打印两个变量;③ {3.14159:.2f} 配合动态宽度 {x:>{w}}。观察它们在 3.11 及以前版本会不会报 SyntaxError。
  8. (t-string 安全拼接)用 t"..." 写一个 render_sql(tpl):把模板渲染成 (SQL 文本, 参数 tuple),把 user = "Bob'; DROP TABLE t;--" 插进去,打印 SQL 文本和参数 tuple,说明为什么恶意字符串不会进入 SQL 文本。

小结

  • 格式化三代:%(老式)→ .format()(第二代)→ f-string(3.6+,推荐);f-string 支持表达式、对齐、= 调试写法。
  • f-string 现代能力(3.12 PEP 701 重写,3.15 实测):嵌套同款引号、表达式内反斜杠、字典键直写、表达式内注释、多行表达式、= 调试语法增强、动态格式宽度;但不要用 f-string 拼接用户输入构造 SQL。
  • t-string(PEP 750,3.15):t"..." 返回 string.templatelib.Template,构造时表达式立即求值但不拼文本 ,str(t) 返回结构 repr;通过 __iter__ 交替吐出字面片段与 Interpolation(.value/.expression/.conversion/.format_spec),由自写渲染器做参数化(SQL)或转义(HTML)等安全拼接,呼应 Day34 数据库与 Day42 Web。
  • 编码:ASCII → Unicode → UTF-8;乱码 = 编解码不一致;str.encode("utf-8") 编码为 bytes,bytes.decode("utf-8") 解码回 str,前后同编码就不乱码。
  • 高频方法:find/index(查找)、count(统计)、replace(替换)、split/join(拆/连)、strip/lstrip/rstrip(去空白)、lower/upper/title(大小写)、startswith/endswith/isalpha/isdigit(判断)。
  • 拼接五法:少量用 + 或 f-string;批量先收集列表再 join(性能最好);循环里别 +=。
  • 所有字符串方法都返回新串,不改原串(不可变性)。

扩展阅读

相关推荐
学页官方1 小时前
部署实战】教培系统私有化部署全流程:从云服务器到上线验收
运维·服务器
syagain_zsx1 小时前
ODB 与 MySQL:C++ 里的 ORM 实践(类即表、事务铁律与查询封装)
开发语言·数据库·c++·mysql·工具库·1024程序员节
BD_Marathon1 小时前
【Python】列表推导式
python
2501_948122631 小时前
Qs 跨端三方库仓颉适配全流程
python·react native·django·tornado
萌动的小火苗2 小时前
MQTT的QoS0、QoS1、QoS2有什么区别?
开发语言·网络·python·php·信息与通信
买房动力十足2 小时前
秒杀商城 + AI 运营:Lua 防超卖、MQ 削峰,AI 负责选品和策划
开发语言·人工智能·lua
forest_092 小时前
《大模型原理通俗讲》系列 00|开篇 大模型到底是怎么回事
人工智能·python·prompt·agi
指艺2 小时前
VirtualBox安装fedora完成后重启,仍提示安装fedora
运维·服务器
silvamux_2 小时前
10款模型写“君幸食”讲解词:统一事实档案与逐款审校
开发语言·php