第一个 Python 程序
"Hello, World!" 是几乎所有编程语言的第一课。本节将带你从零写出第一个 Python 程序,理解 print() 函数、源码文件的组织方式、注释与编码规范,并弄清交互式模式与脚本模式的区别。完成后,你就拥有了独立运行 Python 代码的完整能力。
前置知识
阅读本节前,建议先了解:Python 是什么 与 CPython 解释器原理,理解代码从源码到执行的流程。
基础概念
Python 程序的最基本动作是「输出」。输出通过内置函数 print() 完成,它把参数转换成字符串并写入标准输出(Standard Output,通常是终端)。一个 Python 源文件就是一个以 .py 结尾的纯文本文件,解释器自上而下逐行执行,没有 main 函数等样板代码。
| 术语 | 英文 | 说明 |
|---|---|---|
| 源码文件 | Source File | 以 .py 结尾的文本文件 |
| 内置函数 | Built-in Function | 无需导入即可使用的函数,如 print、len |
| 标准输出 | Standard Output (stdout) | 程序正常输出的目标 |
| 注释 | Comment | 以 # 开头,解释器忽略 |
| 编码声明 | Encoding Declaration | 声明源文件的字符编码 |
| 交互式模式 | Interactive Mode | 逐行输入并立即执行 |
语法与用法
最简的 Python 程序只有一行:
# 最简可运行示例:输出一行文本
print("Hello, World!")Hello, World!把这一行保存为 hello.py,然后在终端运行:
# 查看当前 Python 版本,确认环境可用
python3 --version
# 运行脚本文件
python3 hello.pyPython 3.12.5
Hello, World!详细说明
print() 函数的完整用法
print() 看似简单,实际参数很丰富。它的签名可概括为 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
*objects | 任意 | — | 要输出的对象,可传多个,用逗号分隔 |
sep | str | None | ' '(空格) | 多个对象之间的分隔符 |
end | str | None | '\n'(换行) | 输出结束后的字符 |
file | 文件对象 | sys.stdout | 输出目标,可重定向到文件 |
flush | bool | False | 是否立即刷新缓冲区 |
# 多个参数会被空格连接
print("Python", "是一门", "编程语言")
# 自定义分隔符
print("2026", "10", "08", sep="-")
# 自定义结束符:不换行,同一行继续输出
print("加载中", end="")
print("...", end="")
print("完成")
# 输出空行
print()Python 是一门 编程语言
2026-10-08
加载中...完成参数之间还可以使用 * 解包序列,这在批量输出时很方便:
# 用 * 解包列表作为多个参数
columns = ["姓名", "年龄", "城市"]
print(*columns, sep=" | ")
# 解包 range 生成序列
print(*range(1, 6), sep=", ")姓名 | 年龄 | 城市
1, 2, 3, 4, 5注释与文档字符串
Python 支持三种注释形式,用途各不相同:
# 单行注释:以 # 开头,一直作用到行尾
print("这行代码有效") # 行尾注释同样以 # 开头
"""
多行字符串(Docstring):
放在模块、类或函数的第一行时,会被解释器识别为文档字符串,
可通过 __doc__ 属性或 help() 查看。它不是真正意义上的注释,
只是一段未被赋值的字符串表达式。
"""
def greet(name: str) -> str:
"""返回一句问候语(这是函数的文档字符串)"""
return f"你好,{name}!"
print(greet("Python"))
print(greet.__doc__) # 读取文档字符串这行代码有效
你好,Python!
返回一句问候语(这是函数的文档字符串)字符串不是注释
裸写的多行字符串只是「未被使用的表达式」,Python 不会报错,但它仍会被编译进代码对象。真正的注释应使用 #。文档字符串有明确用途(生成文档、help() 输出),不应与注释混用。
交互式模式与脚本模式的差异
两种模式的执行行为不同,这是初学者最容易困惑的坑:
# 进入交互式 REPL(Read-Eval-Print Loop)
python3>>> 1 + 2 # 表达式会被自动打印
3
>>> print("hi") # print 的返回值是 None,不显示
hi
>>> exit() # 退出在脚本文件中,只有 print() 才有输出:
# 脚本模式:表达式结果不会被自动打印
1 + 2 # 无任何输出(结果被丢弃)
print(1 + 2) # 显式打印,输出 33| 对比项 | 交互式模式 | 脚本模式 |
|---|---|---|
| 触发方式 | 直接输入 python3 | python3 file.py |
| 表达式结果 | 自动打印 | 不打印 |
| 提示符 | >>> 与 ... | 无 |
| 适用场景 | 试验语法、调试片段 | 编写可复用程序 |
| 多行代码 | 需用空行结尾 | 直接书写缩进块 |
编码、缩进与文件编码声明
Python 3 源码默认使用 UTF-8 编码,因此可以直接书写中文,无需声明:
# Python 3 默认 UTF-8,中文可直接使用
message: str = "你好,世界!"
print(message)
# 若因历史原因使用非 UTF-8 编码,需在文件首行声明(仅 Python 2 必需)
# -*- coding: utf-8 -*-你好,世界!缩进是 Python 的语法,而非风格建议。同一代码块必须使用一致的缩进(推荐 4 个空格):
# 正确:4 空格缩进
def check(value: int) -> str:
if value > 0:
return "正数"
return "非正数"
print(check(5))
print(check(-1))正数
非正数# 错误!混用 Tab 与空格会触发 TabError
def broken(value: int) -> str:
if value > 0: # 这里用了 Tab
return "正数" # 这里用了空格
return "非零"输入与输出的结合
input() 函数从标准输入读取一行文本,返回值总是 str 类型:
# 读取用户输入并处理
name = input("请输入你的名字:") # 例如输入:小码农
print(f"你好,{name}!欢迎学习 Python。")
# 注意:input() 返回字符串,做算术需显式转换
age_text = input("请输入你的年龄:") # 例如输入:28
age = int(age_text)
print(f"明年你 {age + 1} 岁")请输入你的名字:小码农
你好,小码农!欢迎学习 Python。
请输入你的年龄:28
明年你 29 岁不要忘记类型转换
input() 永远返回字符串。直接对输入做算术会触发 TypeError。必须先用 int()、float() 转换。
# 错误!字符串与整数不能相加
age = input("年龄:") # 返回 "28"
# print(age + 1) # TypeError: can only concatenate str (not "int") to str
# 正确:先转换类型
age = int(input("年龄:"))
print(age + 1)年龄:28
29程序入口与 __name__
标准库与其他模块导入你的文件时,__name__ 的值是模块名;直接运行时是 "__main__"。这是控制「仅直接运行才执行」的关键:
# 演示:查看 __name__ 的值
print(f"当前 __name__ = {__name__}")
def main() -> None:
"""程序主逻辑"""
print("主逻辑执行中")
# 仅当本文件被直接运行时才执行 main()
if __name__ == "__main__":
main()当前 __name__ = __main__
主逻辑执行中如果这个文件被其他文件 import,则 __name__ 会是模块名,main() 不会执行——这正是脚本既能独立运行、又能被复用的原因。
实战示例
示例一:个人信息卡片生成器
把输入、类型转换、格式化输出组合成一个完整小工具:
def build_card(name: str, age: int, city: str, job: str) -> str:
"""根据个人信息生成一张文本卡片"""
border = "=" * 30
lines = [
border,
f"{'个人信息卡片':^24}", # ^ 表示居中对齐
border,
f"姓 名:{name}",
f"年 龄:{age} 岁",
f"城 市:{city}",
f"职 业:{job}",
border,
]
return "\n".join(lines)
def main() -> None:
"""采集信息并输出卡片"""
name = input("姓名:")
age = int(input("年龄:"))
city = input("城市:")
job = input("职业:")
print()
print(build_card(name, age, city, job))
if __name__ == "__main__":
main()姓名:小码农
年龄:28
城市:杭州
职业:后端工程师
==============================
个人信息卡片
==============================
姓 名:小码农
年 龄:28 岁
城 市:杭州
职 业:后端工程师
==============================示例二:命令行问候工具
下面这个脚本读取命令行参数,输出定制问候,并演示如何输出到文件:
import sys
from datetime import datetime
from pathlib import Path
def greet(names: list[str]) -> str:
"""生成对所有名字的问候语"""
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
lines = [f"[{now}] 你好,{name}!" for name in names]
return "\n".join(lines)
def main() -> None:
"""读取命令行参数,输出问候并写入日志文件"""
# sys.argv[0] 是脚本名,之后的才是用户参数
names = sys.argv[1:] or ["世界"]
result = greet(names)
print(result)
# 同时写入日志文件,便于留痕
log_file = Path("greeting.log")
with log_file.open("a", encoding="utf-8") as file:
file.write(result + "\n")
print(f"(已追加写入 {log_file})")
if __name__ == "__main__":
main()# 运行示例
python3 greet.py Python PHP Go[2026-10-08 10:30:00] 你好,Python!
[2026-10-08 10:30:00] 你好,PHP!
[2026-10-08 10:30:00] 你好,Go!
(已追加写入 greeting.log)示例三:常见输出格式速查
print() 结合 f-string 可完成各类格式化输出:
| 需求 | 写法 | 输出 |
|---|---|---|
| 右对齐数字 | f"{42:>8}" | 42 |
| 左对齐文本 | `f"{'abc':<8} | "` |
| 居中 | f"{'标题':^10}" | 标题 |
| 保留两位小数 | f"{3.14159:.2f}" | 3.14 |
| 千分位 | f"{1234567:,}" | 1,234,567 |
| 百分比 | f"{0.856:.1%}" | 85.6% |
| 补零 | f"{7:03d}" | 007 |
# 格式化输出综合演示
price = 1299.5
discount = 0.85
count = 7
print(f"原价:{price:>12,.2f} 元")
print(f"折扣:{discount:>12.1%}")
print(f"折后:{price * discount:>12,.2f} 元")
print(f"编号:{count:03d}")原价: 1,299.50 元
折扣: 85.0%
折后: 1,104.58 元
编号:007注意事项
input()返回字符串:做数学运算前必须用int()或float()转换,否则触发TypeError。- 缩进必须一致:同一代码块内不能混用 Tab 和空格,推荐统一使用 4 个空格。
- 脚本模式不会自动打印表达式:只有
print()才有输出。 - 字符串不是注释:裸写的多行字符串会被编译进代码,只有
#才是真正的注释。 - 文件名不要用中文或特殊字符:尽量用小写英文加下划线,避免跨平台问题。
python与python3可能不同:macOS/Linux 上建议始终使用python3。- 避免文件名为
os.py等标准库名:会遮蔽标准库模块,导致诡异错误。
最佳实践
- 代码块顶部写模块文档字符串:说明脚本用途,便于他人与工具理解。
- 使用
if __name__ == "__main__":包裹主逻辑:让文件可导入、可测试。 - 优先使用 f-string:Python 3.6+ 的 f-string 可读性与性能都优于
%和str.format()。 - 用
pathlib处理路径:不要手写/或\拼接,避免跨平台问题。 - 把常量提取为具名变量:如
BORDER = "=" * 30,避免魔法值散落。 - 写清晰的函数名与类型提示:即使简单脚本,也养成标注参数类型的习惯。
# 推荐:结构清晰的脚本模板
#!/usr/bin/env python3
"""脚本模板:展示推荐的代码组织方式"""
import sys
BORDER: str = "=" * 40
def main(argv: list[str]) -> int:
"""程序入口,返回退出码"""
print(BORDER)
print(f"参数数量:{len(argv)}")
print(BORDER)
return 0
if __name__ == "__main__":
# 用 SystemExit 把退出码传给操作系统
raise SystemExit(main(sys.argv[1:]))========================================
参数数量:0
========================================下一节
继续学习:使用 Python 作为计算器