input()、print()、strip()、format()、f-string——这些是每个 Python 初学者最早接触的函数,但恰恰因为"太基础",不少开发者用了很多年依然会在细节上踩坑。比如 strip() 到底删什么字符?format mini-language 里的 , 和 .2f 有什么区别?f-string 里能不能调用函数?这篇文章把这些点逐一拆开,配上可运行的代码,帮你把基础真正夯实。
input() 和 print() 的隐藏行为
input() 总是返回字符串,不管用户敲的是数字还是路径。这是最常被遗忘的一点:
age = input("请输入年龄:")
# 用户输入 25,age 是 "25",不是 25
# 直接做算术会报 TypeError
# age + 1 → TypeError: can only concatenate str to str
age_int = int(age) # 必须显式转换
print() 的 sep 和 end 参数经常被忽略,但它们在日志和格式化输出中非常实用:
# 用逗号分隔多个值,末尾不加换行
print("user_id", "login", "success", sep=",", end=";\n")
# 输出: user_id,login,success;
print() 还支持 file 参数,可以直接写入文件对象,省去 write() + 换行拼接:
with open("log.txt", "a") as f:
print("2024-01-15 task done", file=f)
strip 家族:不只是去空格
strip()、lstrip()、rstrip() 删除的并不是"空格",而是所有位于边缘的指定字符。默认字符集包括空格、\t、\n、\r、\x0b、\x0c。你可以传入自定义字符:
path = "/usr/local/bin/"
path.rstrip("/") # '/usr/local/bin' — 去掉尾部斜杠
raw = ">>> hello <<<"
raw.strip(">< ") # 'hello' — 同时去掉 > < 和空格
# 注意:strip 是两端同时删,不是只删一头
" mid ".strip() # 'mid'
一个常见误用:想删固定前缀时用 strip,但它会删所有匹配字符,直到遇到不匹配的为止:
filename = "___config.yaml"
filename.strip("_") # 'config.yaml' — 意料之中
filename = "__init__.py"
filename.strip("_") # 'init.py' — 如果只想删前缀,应该用 lstrip 或 removeprefix
filename.removeprefix("__") # 'init__.py' — Python 3.9+,精确删前缀
format mini-language:一个被低估的微型 DSL
str.format() 的格式说明符 {:spec} 内部有一套完整的 mini-language,远不止 .2f。几个实用组合:
# 千分位逗号 + 两位小数
revenue = 1234567.891
print("{:,.2f}".format(revenue)) # 1,234,567.89
# 居中对齐,宽度 20,填充字符 ~
title = "REPORT"
print("{:~^20}".format(title)) # ~~~~~~~REPORT~~~~~~~
# 百分比显示
ratio = 0.834
print("{:.1%}".format(ratio)) # 83.4%
# 二进制 / 八进制 / 十六进制
num = 255
print("{:b}".format(num)) # 11111111
print("{:o}".format(num)) # 377
print("{:#x}".format(num)) # 0xff — # 加前缀
mini-language 的语法是 [fill][align][sign][#][0][width][grouping_option][.precision][type],可以自由组合。理解了这个结构,你就不需要每次都去查文档了。
f-string:现代 Python 的首选方式
f-string 从 Python 3.6 引入,在可读性和性能上都优于 % 格式化和 str.format()。它支持表达式、函数调用、调试语法(3.8+):
name = "Ada"
score = 97.5
# 基本用法
msg = f"{name} scored {score:.1f}" # 'Ada scored 97.5'
# 调用函数
def upper(s):
return s.upper()
print(f"{upper(name)}") # 'ADA'
# 调试语法 (Python 3.8+)
print(f"{name=}, {score=}") # name='Ada', score=97.5
# 多行 f-string
report = (
f"Name: {name}\n"
f"Score: {score:.1f}\n"
f"Status: {'pass' if score >= 60 else 'fail'}"
)
print(report)
f-string 里不能用反斜杠(\n 等),但你可以提前把换行符存到变量里再引用。嵌套大括号可以控制格式精度:
width = 10
precision = 2
value = 3.14159
print(f"{value:{width}.{precision}f}") # ' 3.14'
实战:一个迷你命令行日志格式化工具
把上面所有知识点串起来,写一个可以直接跑的小脚本——从用户输入读取日志条目,清洗、格式化后输出到终端和文件:
#!/usr/bin/env python3
"""mini_log_formatter.py — 演示 input/print/strip/format/f-string 综合用法"""
import datetime
def clean_tag(raw: str) -> str:
"""去掉前后空白和特殊符号,保留核心标签"""
return raw.strip().strip("><").lower()
def format_entry(timestamp, tag, message, width=12):
"""用 f-string + mini-language 格式化单条日志"""
return f"[{timestamp}] {tag:~<{width}} | {message}"
def main():
print("=== 日志格式化工具 ===", end="\n\n")
# input() 总返回 str,需要自行清洗
raw_tag = input("输入标签(如 >>> ERROR <<<):")
tag = clean_tag(raw_tag)
raw_msg = input("输入日志内容:")
msg = raw_msg.strip() # 只去空白,不去其他字符
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
entry = format_entry(timestamp, tag, msg)
# 终端输出,用 sep 简化
print(entry)
# 同时写入文件,用 print 的 file 参数
with open("mini_log.txt", "a") as f:
print(entry, file=f)
# 用 format mini-language 做统计摘要
print("\n--- 统计 ---")
print(f"标签长度: {len(tag)}")
print(f"原始输入: {raw_tag!r}") # !r 显示 repr
print("{:^30}".format("END OF ENTRY"))
if __name__ == "__main__":
main()
运行方式:
python3 mini_log_formatter.py
# 交互输入后,终端和 mini_log.txt 都会收到格式化日志
选用建议与易错清单
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 日常字符串拼接 | f-string | 可读性最好,性能最高 |
| 需要动态格式参数 | str.format() |
f-string 嵌套大括号可读性差 |
| 旧代码 / 日志库 | % 格式化 |
兼容性,但新项目不建议 |
| 删固定前缀/后缀 | removeprefix/removesuffix (3.9+) |
精确,不会误删 |
| 删边缘任意字符 | strip/lstrip/rstrip |
灵活,但要留意"删到不匹配为止"的行为 |
几个高频踩坑点,值得加到团队 checklist:
input()返回 str——做数值运算前必须int()/float()。strip()不是trim()——它删字符集,不是只删空格;删前缀优先用removeprefix。- f-string 里不能写
\n——提前赋值给变量再引用。 !r和!s调整显示方式——f"{value!r}"输出 repr,调试时很有用。print(end=..., sep=..., file=...)——三个参数能省掉不少手动拼接。
把这些细节吃透,"基础"才不会成为隐患。