02 - 第一个 Python 程序
终于要开始写代码了。这章我们会写几个小程序,把最基本的东西过一遍。
Hello World 的仪式感
学任何编程语言,第一件事都是打印一句"Hello World"。这算是程序员圈子里的一个传统了,据说从 1978 年的 C 语言教材就开始了。
打开你的项目,在 hello.py 里写上:
python
print("Hello World")
然后在终端里运行:
bash
uv run hello.py
屏幕上出现 Hello World 了?恭喜你,你已经是一个 Python 程序员了(虽然还很初级哈哈)。
你可能会觉得这也太简单了吧。确实,但别小看这一行------你已经学会了 Python 里用得最多的函数之一:print()。
print() 的几种用法
print() 最基本的用法就是打印一段文字:
python
print("我在学 Python")
你也可以打印数字,不用加引号:
python
print(42)
print(3.14)
想打印多个东西,用逗号隔开就行:
python
print("我叫", "小明", "今年", 25, "岁")
输出:我叫 小明 今年 25 岁
逗号会自动在每个内容之间加一个空格。
你也可以换分隔符:
python
print("2024", "05", "25", sep="-")
输出:2024-05-25
或者让打印完不换行:
python
print("你好", end="")
print("世界")
输出:你好世界(在同一行)
默认情况下 print() 打印完会自动换行,end="" 就是告诉它"结尾什么都别加"。
跟用户对话:input()
光让程序说话没意思,得让它能听你说话。input() 就是干这个的------它会暂停程序,等你在键盘上输入点东西。
新建一个文件 greet.py:
python
name = input("你叫什么名字?")
print("你好," + name + "!欢迎来到 Python 的世界")
运行一下:
bash
uv run greet.py
它会问你名字,你输入之后它会跟你打招呼。
有个要注意的地方:input() 拿到的东西永远是字符串(就是文字),哪怕你输入的是数字。
python
age = input("你多大了?")
print(type(age)) # <class 'str'>
所以你如果要做数学运算,得先转一下类型:
python
age = input("你多大了?")
age = int(age) # 把字符串转成整数
print("你明年就", age + 1, "岁了")
int() 是把文字转成整数的函数。后面会详细讲这些类型转换,现在先有个印象就行。
注释:写给人看的话
写代码的时候经常需要在旁边加点说明,告诉别人(或者以后的自己)这段代码是干嘛的。这些说明叫"注释",Python 解释器会忽略它们。
单行注释用 #:
python
# 这是一个注释,Python 不会执行它
print("你好") # 行尾也可以写注释
多行注释可以用三个引号:
python
"""
这是一个多行注释
可以写好几行
通常用来给函数或类写说明文档
"""
print("你好")
说实话,严格来讲三个引号那个不算注释,它其实是一个没被赋值给任何变量的字符串。但因为 Python 会忽略这种孤立的字符串,效果跟注释差不多。大部分人就直接叫它多行注释了。
注释该写多少?
新手容易走两个极端:要么一行注释都不写,要么每行都写。
我的建议是------写那些"为什么"而不是"是什么"。
不太好的注释:
python
# 把 x 设为 10
x = 10
这注释说了等于没说,看代码就知道 x 是 10。
好的注释:
python
# 最大重试次数设为 10,超过就放弃
# 因为实际测试发现 10 次已经能覆盖 99% 的情况
max_retries = 10
这个就解释了"为什么是 10",以后看代码的人(包括三个月后的你自己)会觉得感谢。
代码风格:PEP 8
Python 社区有一套公认的代码规范,叫 PEP 8。不用背,大概知道几个要点就行:
缩进用 4 个空格
Python 靠缩进来表示代码块(不像 C/Java 用大括号)。所以缩进不是可选项,是语法的一部分。
python
# 对的
if True:
print("缩进了")
# 错的,没缩进会报错
if True:
print("没有缩进")
用 Tab 还是空格?Python 官方推荐空格。VS Code 默认按一下 Tab 会自动转成 4 个空格,所以不用纠结。
变量名用小写加下划线
python
# 推荐
user_name = "小明"
max_retry_count = 3
# 不推荐
userName = "小明" # 这是 Java/JS 的风格
UserName = "小明" # 这是类的命名方式
运算符两边加空格
python
# 推荐
x = 10 + 5
# 不推荐
x=10+5
这些规则现在不用死记,VS Code 装了 Python 插件之后,写得不规范它会有提示。写多了自然就习惯了。
一个稍完整的例子
来写一个稍微有意思点的程序,把前面学的东西串起来。
新建文件 calculator.py:
python
# 一个超级简单的加法计算器
num1 = input("请输入第一个数字:")
num2 = input("请输入第二个数字:")
# input 拿到的是字符串,要先转成数字
result = float(num1) + float(num2)
print(num1, "+", num2, "=", result)
试试运行:
bash
uv run calculator.py
输入两个数字看看结果。这个程序虽然简单,但它已经具备了程序的基本要素:输入、处理、输出。
你可能会想:如果我输入的不是数字呢?比如输入"abc"?
试试看,你会看到一个报错信息。这是正常的------我们还没学怎么处理错误输入,后面"异常处理"那章会专门讲。现在先别管,知道有这回事就行。
调试技巧:出错了怎么办
写代码一定会遇到报错,这很正常。关键是你得能看懂报错信息,知道怎么找到问题。
看懂报错信息
Python 的报错信息(traceback)是从下往上读的。举个例子:
python
def calculate(x):
return 10 / x
def main():
calculate(0)
main()
运行后的报错:
Traceback (most recent call last):
File "test.py", line 7, in <module>
main()
File "test.py", line 5, in main
calculate(0)
File "test.py", line 2, in calculate
return 10 / x
ZeroDivisionError: division by zero
最后一行 告诉你出了什么错:ZeroDivisionError: division by zero(除以零)。
倒数几行 告诉你错在哪:File "test.py", line 2, in calculate,第 2 行的 calculate 函数里。
上面的部分 是调用链:main() 调用了 calculate(0),calculate 里面出了错。
看报错的核心就三步:
- 看最后一行是什么错误
- 看倒数几行是哪行代码出了问题
- 沿着调用链往上追溯
print 调试法
最简单粗暴的方式------在你觉得可能有问题的地方加 print():
python
def process(data):
print(f"DEBUG: data = {data}") # 看看传入的数据对不对
result = data.strip().lower()
print(f"DEBUG: result = {result}") # 看看处理后的结果
return result
虽然原始,但 80% 的 bug 都能用这种方式找到。我自己到现在还经常用。
pdb:Python 内置调试器
pdb 能让你暂停程序,一行一行地执行,随时查看变量的值:
python
import pdb
def buggy_function(numbers):
total = 0
for n in numbers:
pdb.set_trace() # 程序会在这里暂停
total += n
return total
buggy_function([1, 2, 3])
暂停后你可以输入命令:
| 命令 | 作用 |
|---|---|
n |
执行下一行(不进入函数) |
s |
执行下一行(进入函数) |
c |
继续执行到下一个断点 |
p 变量名 |
打印变量的值 |
l |
查看当前代码上下文 |
q |
退出调试 |
Python 3.7+ 还有个更简洁的写法:直接用 breakpoint() 代替 pdb.set_trace():
python
def buggy_function(numbers):
total = 0
for n in numbers:
breakpoint() # 效果一样,更简洁
total += n
return total
VS Code 调试
如果你用 VS Code,调试更直观:
- 在代码行号左边点一下,会出现一个红点(断点)
- 按
F5启动调试 - 程序会在红点处暂停
- 左侧面板可以看到所有变量的当前值
- 顶部的按钮可以单步执行、继续、跳出等
比 pdb 好用多了,不用记命令。推荐新手直接从 VS Code 调试开始。
pass 和 ...:占位符
有时候你需要一个代码块,但暂时不想写具体内容。比如先搭个框架:
python
# 先用 pass 占位,以后再来写
def not_ready_yet():
pass # 什么都不做,但语法上需要一行代码
class MyError(Exception):
pass # 自定义异常经常这样写
if condition:
do_something()
else:
pass # 暂时不处理这个分支
pass 就是一个"什么都不做"的语句,纯粹为了满足语法要求(Python 不允许空的代码块)。
...(三个点,叫 Ellipsis)也能当占位符用,效果跟 pass 一样:
python
def not_ready_yet():
...
class MyError(Exception):
...
用哪个都行,看个人习惯。我一般用 pass,但有些人喜欢 ... 因为更短。在一些科学计算库(如 NumPy)里 ... 有特殊含义,那是另一回事了。
本章小结
print()用来输出内容,可以打印多个值、自定义分隔符input()用来获取用户输入,拿到的永远是字符串- 注释用
#(单行)或"""..."""(多行),写"为什么"而不是"是什么" - Python 用缩进表示代码块,推荐 4 个空格
- 代码风格遵循 PEP 8,不用刻意背,编辑器会帮你
- 看报错信息:最后一行是错误类型,往上找是哪行代码出了问题
pdb/breakpoint()和 VS Code 断点是两种常用的调试方式pass和...是占位符,满足语法要求但什么都不做
面试题
Q1:print() 和 input() 的返回值分别是什么?
点击查看答案
print() 的返回值是 None。它的作用是把内容输出到屏幕,本身不返回有用的值。
input() 的返回值是用户输入的字符串(str 类型)。哪怕用户输入的是数字 123,input() 返回的也是字符串 "123"。
Q2:Python 中为什么缩进很重要?如果缩进不一致会怎样?
点击查看答案
Python 用缩进来定义代码块(作用域),不像 C/Java 用 {}。缩进决定了哪些代码属于同一个块。
如果缩进不一致(比如混用 Tab 和空格),Python 会报 IndentationError 或 TabError。所以必须保持一致,推荐全部用 4 个空格。
Q3:type() 函数有什么用?type(123) 和 type("123") 的结果一样吗?
点击查看答案
type() 用来查看一个值的类型。
type(123) 返回 <class 'int'>(整数)。
type("123") 返回 <class 'str'>(字符串)。
虽然看起来都是 123,但一个是数字,一个是文字。这在处理 input() 返回值时特别重要------用户输入的数字其实是字符串。
Q4:float("3.14") 和 int("3.14") 都能正常执行吗?
点击查看答案
float("3.14") 可以正常执行,返回 3.14。
int("3.14") 会报错 ValueError。因为 int() 只能转换整数字符串(比如 "3"),不能直接转换带小数点的字符串。
如果要把 "3.14" 转成整数,需要先转 float 再转 int:int(float("3.14")),结果是 3(直接截断小数部分,不四舍五入)。