2. 你的第一个 Python 程序
在第 1 章中,你学习了如何安装 Python、使用交互式命令行(REPL),以及运行简单的脚本文件。你也第一次见到了错误和回溯。现在是时候编写你的第一个真正的 Python 程序了——这些程序能够显示信息、接受用户输入,并产生有意义的结果。
本章会介绍你几乎在每一个 Python 程序中都会用到的基本构建块:用来显示输出的 print() 函数(function),用于为代码编写文档的注释,用于存储数据的变量,以及用来从用户那里获取信息的 input() 函数。到本章结束时,你就能够创建简单但完整的交互式程序,这些程序遵循经典的输入-处理-输出(input-process-output)模式。
2.1) 使用 print() 函数打印文本
print() 函数是 Python 中最重要的工具之一。它会在屏幕上显示文本(以及其他信息),从而让你的程序能够与用户进行沟通。你已经在第 1 章中简单见过 print(),现在我们来深入探索它。
2.1.1) 基本打印
在最简单的情况下,print() 会显示被引号括起来的文本。我们来创建一个脚本文件看看它是如何工作的:
# hello.py
print("Hello, World!")当你运行这个脚本时,Python 会显示:
Hello, World!引号中的文本——"Hello, World!"——称为一个字符串(string)。字符串是由字符(字母、数字、符号、空格)组成的序列,Python 会把它当作文本来处理。我们将在第 5 章更加详细地探索字符串,但现在你可以把它们视为在 Python 中表示文本的方式。
你可以通过把任意文本放在引号里来打印它:
# greetings.py
print("Welcome to Python programming!")
print("This is your first real program.")
print("Python makes programming fun and accessible.")输出:
Welcome to Python programming!
This is your first real program.
Python makes programming fun and accessible.注意,每个 print() 语句都会在单独的一行产生输出。Python 会在每次调用 print() 后自动添加一个换行符(newline),并将光标移动到下一行。
2.1.2) 打印多个项
print() 函数可以在一次调用中显示多个项,只需要用逗号将它们分隔开:
# multiple_items.py
print("Python", "is", "awesome!")
print("I", "am", "learning", "to", "code")输出:
Python is awesome!
I am learning to code当你用逗号分隔各项时,print() 会在它们之间自动插入一个空格。这对于组合多段文本而不必手动添加空格非常方便。
你还可以混合不同类型的数据。例如,你可以同时打印文本和数字:
# mixed_output.py
print("The answer is", 42)
print("Python version", 3.12, "is powerful")输出:
The answer is 42
Python version 3.12 is powerfulPython 会在打印数字时自动把数字转换成文本,因此你暂时不需要担心技术细节。我们将在第 3 章学习更多关于不同数据类型的内容。
2.1.3) 单引号 vs 双引号
Python 对字符串既接受单引号('),也接受双引号(")。对于简单文本而言,两者完全可以互换:
# quotes.py
print("This uses double quotes")
print('This uses single quotes')
print("Both work exactly the same way")输出:
This uses double quotes
This uses single quotes
Both work exactly the same way不过,当文本中包含撇号或引号时,引号的选择就很重要了。如果你的文本中包含撇号(与单引号是同一个字符),就使用双引号把它括起来:
# apostrophes.py
print("It's a beautiful day!")
print("Python's syntax is clean")输出:
It's a beautiful day!
Python's syntax is clean如果你在这里尝试使用单引号,Python 就会糊涂:
# This causes an error:
print('It's a beautiful day!') # Error! Python sees three separate quotes错误产生的原因是,Python 把 "It's" 中的撇号看作字符串的结束,从而导致剩下的 "s a beautiful day!" 成为无效代码。
类似地,如果文本中包含双引号,就使用单引号把它括起来:
# quotations.py
print('She said, "Hello!"')
print('The book is called "Python Basics"')输出:
She said, "Hello!"
The book is called "Python Basics"实践指南:选择一种风格(单引号或双引号),并在代码中始终如一地使用。大多数 Python 程序员喜欢用双引号表示常规字符串,不过两种方式都可以。只有当你的文本包含你通常使用的那种引号字符时,再切换到另一种风格。
2.1.4) 打印空行
有时你希望在输出中添加空行,让其更易读。你可以通过调用不带任何参数的 print() 来做到这一点:
# spacing.py
print("First section of output")
print("More information here")
print() # Empty line
print("Second section of output")
print("This is separated from the first section")输出:
First section of output
More information here
Second section of output
This is separated from the first section这个空的 print() 调用会创建一个空行,通过在视觉上分隔不同的部分,使输出更容易阅读。
2.1.5) 字符串中的特殊字符
有时候你需要在输出中包含一些无法直接输入,或者在 Python 中具有特殊含义的字符。例如,如何在一个字符串中间创建换行?或是为了对齐而插入制表符?Python 提供了转义序列(escape sequence)——以反斜杠(\)开头的特殊两个字符组合——来表示这些字符。
当你需要以特定方式格式化输出——创建多行消息、对齐数据列,或在 Windows 上处理文件路径时,这些转义序列特别有用。随着你编写更多程序,你会经常使用 \n。
最常用的转义序列是 \n,它表示换行符(line break):
# newlines.py
print("First line\nSecond line\nThird line")输出:
First line
Second line
Third line\n 告诉 Python 在字符串的那个位置换到新的一行。当你希望通过一条 print() 语句创建多行输出时,这非常有用。
另一个有用的转义序列是 \t,它表示制表符(水平间距):
# tabs.py
print("Name:\tJohn")
print("Age:\t25")
print("City:\tNew York")输出:
Name: John
Age: 25
City: New York\t 会产生一致的间距,使数值像列一样对齐。
如果你需要在输出中包含实际的反斜杠,请使用 \\:
# backslash.py
print("The file path is C:\\Users\\Documents")输出:
The file path is C:\Users\Documents我们将在第 5 章更深入地探索转义序列和字符串处理。现在,你只需要知道:\n 用于创建新行,\t 用于创建制表符。
2.2) 使用注释解释代码
随着程序变得越来越复杂,解释你的代码在做什么就变得很重要——不论是为了阅读你代码的其他人,还是为了未来的你自己。Python 提供了注释来达到这个目的:这些是写在代码中的说明,在程序运行时 Python 会完全忽略它们。
2.2.1) 单行注释
在 Python 中,一行中出现在 # 符号之后的任何文本都是注释。Python 会忽略从 # 开始直到这一行末尾的所有内容:
# comment_example.py
# This is a comment. Python ignores this line completely.
print("This line runs") # This comment explains the print statement
# print("This line does NOT run because it's commented out")
print("This line also runs")输出:
This line runs
This line also runs注意第二条 print() 语句并没有执行,因为整行都被注释掉了。当你想临时禁用某段代码而不删除它时,这就很有用。
注释既可以单独占一行,也可以出现在代码行的末尾。这两种风格都很常见:
# display_info.py
# Display a welcome message to the user
print("Welcome to the program!")
print("Processing data...") # Inform the user of progress2.2.2) 何时以及如何写好注释
注释应该解释你为什么要这样做,而不仅仅是代码做了什么。下面是一个糟糕注释的例子:
# Bad comment - just repeats what the code obviously does
print("Hello") # Print "Hello"这个注释没有增加任何价值,因为任何阅读代码的人一眼就能看出它打印了 "Hello"。
下面是更好的写法:
# Good comment - explains the purpose or context
# Greet the user before requesting their information
print("Hello")这个注释解释了我们为什么要打印 "Hello"——它是与用户进行更大范围交互的一部分。
编写有用注释的指南:
- 解释目的:这段代码为什么存在?它解决了什么问题?
- 澄清复杂逻辑:如果某些内容不是显而易见的,就解释一下
- 记录重要决策:说明你为什么选择某种实现方式而不是另一种
- 提示坑点:指出任何可能令人困惑或出乎意料的地方
- 保持同步更新:当你修改代码时,也要更新注释
下面的例子展示了有效注释的写法:
# temperature_converter.py
# This program converts temperatures from Fahrenheit to Celsius
# Formula: C = (F - 32) × 5/9
# Display program title
print("Temperature Converter")
print("Fahrenheit to Celsius")
print()
# We'll learn how to get user input in section 2.4
# For now, we'll use a fixed temperature value
fahrenheit = 75 # Temperature in Fahrenheit to convert
# Perform the conversion using the standard formula
# Subtract 32 first (order matters due to the formula)
celsius = (fahrenheit - 32) * 5 / 9
# Display the result
print("Temperature:", fahrenheit, "°F =", celsius, "°C")输出:
Temperature Converter
Fahrenheit to Celsius
Temperature: 75 °F = 23.88888888888889 °C注意这些注释如何解释程序的目的、所用的公式以及计算背后的逻辑。它们让代码变得更加容易理解,尤其是对于第一次接触这段代码的人而言。
2.2.3) 多行注释和文档字符串
对于较长的说明,你可以使用多行单行注释:
# multi_line_comments.py
# This program demonstrates a longer explanation
# that spans multiple lines. Each line starts
# with a # symbol.
print("Program starts here")Python 并不像某些其他语言那样有专门的多行注释语法。不过,可以使用三引号字符串作为一种替代方式。我们会在第 19 章学习更多关于文档字符串(docstring)的内容(函数的文档字符串),这里先简单预览一下:
# docstring_preview.py
"""
This is a multi-line string that can serve as a comment.
It's not technically a comment—it's a string that Python
creates but doesn't use. However, it's often used for
longer explanations at the beginning of files.
"""
print("Program starts here")目前,先坚持使用 # 来写注释。我们会在后面的章节中探索三引号字符串以及它们的正确用法。
2.2.4) 为测试目的注释掉代码
注释还可以用来在测试过程中临时禁用代码:
# testing.py
print("This always runs")
# print("This is disabled for testing")
print("This also always runs")这一技巧称为“注释掉代码”(commenting out)。当你想测试程序在没有某些代码行时会如何表现,但又不想永久删除这些代码时,这个方法就很有用。
2.3) 引入变量和赋值(预览)
当程序能够存储和操作数据时,它们就会变得更加有用。变量是用来保存值的具名容器。你可以把变量想象成一个贴了标签的盒子,你可以把信息放到里面,之后再取出来使用。
重要说明:本节提供的是对变量的预览,帮助你理解本章中的示例。我们将在第 3 章全面深入地探索变量,包括命名规则、数据类型,以及 Python 在内部是如何处理变量的。现在,我们先专注于变量的基本概念和用法。
2.3.1) 使用赋值创建变量
你可以使用赋值运算符(=)来创建变量。基本形式是:
variable_name = value变量名写在左边,值写在右边,用 = 连接:
# variables_basic.py
message = "Hello, Python!"
print(message)输出:
Hello, Python!这里发生了什么:
- Python 创建了一个名为
message的变量 - Python 把字符串
"Hello, Python!"存储到这个变量中 - 当我们在
print()函数中使用message时,Python 会取出存储的值并显示出来
变量可以存储不同类型的数据。下面是一些例子:
# variable_types.py
greeting = "Welcome!" # A string (text)
age = 25 # A number (integer)
price = 19.99 # A number with a decimal point (float)
is_student = True # A boolean (True or False)
print(greeting)
print(age)
print(price)
print(is_student)输出:
Welcome!
25
19.99
True我们将在第 3 章学习这些不同的数据类型(字符串、整数、浮点数、布尔值)。现在,只要明白变量可以保存多种不同类型的信息就够了。
2.3.2) 变量为什么有用
变量让你的代码更加灵活,也更容易维护。对比下面两种方式:
没有变量:
# no_variables.py
print("Welcome, John!")
print("John, your account balance is $1000")
print("Thank you for banking with us, John!")使用变量:
# with_variables.py
name = "John"
balance = 1000
print("Welcome,", name + "!")
print(name, "your account balance is $", balance)
print("Thank you for banking with us,", name + "!")两个程序产生的输出类似,但使用变量的版本有明显优势:
- 易于更新:如果要修改名字,你只需要改一行(
name = "John"),而不是三行 - 减少错误:你不会在某处不小心拼错名字
- 更灵活:之后你可以改变
name的取值方式(例如通过询问用户)
2.3.3) 变量的重新赋值
变量在程序执行过程中可以改变它们的值。这称为重新赋值(reassignment):
# reassignment.py
score = 0
print("Initial score:", score)
score = 10
print("After first update:", score)
score = 25
print("After second update:", score)输出:
Initial score: 0
After first update: 10
After second update: 25每当你给变量赋予一个新值时,Python 就会用新值替换旧值。之前的值会被丢弃。
你甚至可以使用变量当前的值来计算它的新值:
# updating_values.py
count = 5
print("Starting count:", count)
count = count + 1 # Add 1 to count
print("After adding 1:", count)
count = count + 10 # Add 10 to count
print("After adding 10:", count)输出:
Starting count: 5
After adding 1: 6
After adding 10: 16这种模式——count = count + 1——在编程中极其常见。它的意思是:“取当前的 count 值,加 1,然后把结果重新存回 count。”我们会在第 4 章学习这种写法的简写形式(count += 1)。
2.3.4) 变量命名预览
Python 中的变量名必须遵守一定规则:
- 可以包含字母、数字和下划线(
_) - 必须以字母或下划线开头(不能以数字开头)
- 不能包含空格或诸如
@、$、%等特殊字符 - 不能是 Python 关键字(保留字,如
print、if、for等)
下面是一些合法的变量名:
# valid_names.py
user_name = "Alice"
age2 = 30
_private_value = 42
totalPrice = 99.99以及一些非法的变量名:
# These cause errors:
# 2age = 30 # Cannot start with a number
# user-name = "Alice" # Cannot contain hyphens
# total price = 99.99 # Cannot contain spaces
# print = "Hello" # Cannot use Python keywords最佳实践:使用能够说明变量代表含义的描述性名称。user_age 比 a 更好,total_price 比 tp 更好。我们将在第 3 章详细讨论命名约定。
2.3.5) 变量让程序更具动态性
当你使用变量让程序变得更具动态性时,变量的真正威力就显现出来了:
# dynamic_greeting.py
name = "Alice"
age = 28
city = "Seattle"
print("Personal Information")
print("====================")
print("Name:", name)
print("Age:", age)
print("City:", city)
print()
print("Summary:", name, "is", age, "years old and lives in", city)输出:
Personal Information
====================
Name: Alice
Age: 28
City: Seattle
Summary: Alice is 28 years old and lives in Seattle通过修改程序顶部 name、age 和 city 的值,你就可以在不改动任何 print() 语句的情况下定制整个输出。将数据与逻辑分离是良好编程的一个基本原则。
展望:在第 3 章中,我们会全面探索变量,包括数据类型、类型转换、命名规则,以及 Python 在内部是如何管理变量的。现在,你已经有足够的认识,可以在简单程序中使用变量了。
2.4) 使用 input() 从键盘读取输入
到目前为止,我们程序中的所有数据都是硬编码的——直接写在代码里。但真实的程序往往需要与用户交互,接收他们提供的信息。Python 的 input() 函数就能做到这一点。
2.4.1) 基本输入
input() 函数会显示一条消息(称为提示,prompt),然后等待用户输入内容并按下回车。基本形式如下:
# basic_input.py
name = input("What is your name? ")
print("Hello,", name + "!")当你运行这个程序时,会发生如下过程:
What is your name? Alice
Hello, Alice!我们来分解一下:
- Python 执行
input("What is your name? ") - Python 显示提示:
What is your name? - 程序暂停,等待用户输入
- 用户输入
Alice并按下回车 - Python 把文本
"Alice"存入变量name - 程序继续执行,打印问候语
你传给 input() 的文本就是提示——即用户在输入前看到的内容。始终在提示末尾包含一个空格(注意问号后面的空格),以便将提示语与用户输入分开,使其更易读。
2.4.2) input 总是返回字符串
这一点非常关键:input() 始终返回字符串,即使用户输入的是数字:
# input_as_string.py
age = input("How old are you? ")
print("You entered:", age)
print("The type is:", type(age))当你运行程序并输入 25 时:
How old are you? 25
You entered: 25
The type is: <class 'str'>即便用户输入了 25,Python 存储的是字符串 "25",而不是数字 25。type() 函数验证了这一点——它表明 age 是字符串(str),不是整数。
当你想做运算时,这一点就很重要了。你无法直接对字符串做数学运算:
# This causes an error:
age = input("How old are you? ")
next_year_age = age + 1 # Error! Can't add a number to a string这会产生错误,因为 Python 不知道如何把数字 1 加到字符串 "25" 上。
2.4.3) 将输入转换为数字
如果想把输入当作数字使用,就必须显式地用 int()(用于整数)或 float()(用于小数)进行转换:
# input_conversion.py
age_string = input("How old are you? ")
age = int(age_string) # Convert string to integer
next_year = age + 1
print("Next year, you will be", next_year, "years old")当你运行这个程序并输入 25 时:
How old are you? 25
Next year, you will be 26 years old你也可以在一行中把输入和转换合并:
# input_conversion_compact.py
age = int(input("How old are you? "))
next_year = age + 1
print("Next year, you will be", next_year, "years old")这种写法更简洁,也是你最常见到的风格。它是从内到外执行的:
input("How old are you? ")以字符串形式获取用户输入int(...)将该字符串转换为整数- 这个整数被存储到变量
age中
下面是一个使用 float() 处理小数的例子:
# float_input.py
price = float(input("Enter the price: $"))
tax_rate = 0.08
tax = price * tax_rate
total = price + tax
print("Price: $", price)
print("Tax: $", tax)
print("Total: $", total)当你运行这个程序并输入 19.99 时:
Enter the price: $19.99
Price: $ 19.99
Tax: $ 1.5992
Total: $ 21.5892重要说明:如果用户输入的文本无法转换为数字,Python 就会抛出错误。例如,如果你使用 int(input("Enter a number: ")),而用户输入 "hello",Python 无法将 "hello" 转换为整数,就会显示错误信息。我们会在第 27 章学习如何优雅地处理这些情况(异常处理),让你的程序能够从错误中恢复并提示用户重新输入。
2.4.4) 多次输入
程序经常需要从用户那里获取多个信息。只需多次调用 input() 即可:
# multiple_inputs.py
print("Please enter your information:")
print()
first_name = input("First name: ")
last_name = input("Last name: ")
age = int(input("Age: "))
city = input("City: ")
print()
print("Summary")
print("=======")
print("Name:", first_name, last_name)
print("Age:", age)
print("Location:", city)示例交互:
Please enter your information:
First name: John
Last name: Smith
Age: 30
City: Boston
Summary
=======
Name: John Smith
Age: 30
Location: Boston注意程序是如何逐一提示每一项信息的。这使得用户清楚地知道需要提供什么信息、以及顺序如何。
2.4.5) 创建有信息量的提示
良好的提示能让你的程序更易用。下面是一些指南:
明确你需要什么:
# Good prompts
name = input("Enter your full name: ")
temperature = float(input("Enter temperature in Fahrenheit: "))
quantity = int(input("How many items do you want to purchase? "))标明期望格式或单位:
# format_prompts.py
date = input("Enter date (MM/DD/YYYY): ")
phone = input("Enter phone number (XXX-XXX-XXXX): ")
price = float(input("Enter price in dollars (without $): "))使用清晰、友好的语言:
# friendly_prompts.py
print("Welcome to the Temperature Converter!")
print()
temp = float(input("Please enter a temperature in Fahrenheit: "))清晰的提示可以减少用户困惑,让你的程序更专业。
2.5) 简单的输入-处理-输出程序
大多数程序都遵循一个常见模式,称为输入-处理-输出(Input-Process-Output, IPO):
- 输入(Input):从用户或其他来源获取数据
- 处理(Process):对数据进行计算或转换
- 输出(Output):显示结果
这个模式非常基础,你在整个编程旅程中会在无数程序中使用它。下面我们通过几个完整的例子来探索它。
2.5.1) 示例:温度转换器
我们来创建一个完整的程序,把华氏温度转换为摄氏温度:
# temperature_converter.py
# This program converts a temperature from Fahrenheit to Celsius
# Formula: C = (F - 32) × 5/9
print("Temperature Converter")
print("Fahrenheit to Celsius")
print("=" * 30) # Print a line of equal signs
print()
# INPUT: Get temperature from user
fahrenheit = float(input("Enter temperature in Fahrenheit: "))
# PROCESS: Convert using the formula
celsius = (fahrenheit - 32) * 5 / 9
# OUTPUT: Display the result
print()
print("Result:", fahrenheit, "°F =", celsius, "°C")示例交互:
Temperature Converter
Fahrenheit to Celsius
==============================
Enter temperature in Fahrenheit: 75
Result: 75.0 °F = 23.88888888888889 °C注意程序是如何清晰地遵循 IPO 模式的:
- 输入:获取华氏温度
- 处理:应用转换公式
- 输出:显示摄氏温度结果
代码中的注释明确标出了这三个部分,使程序结构一目了然。
2.5.2) 示例:矩形面积计算器
下面是另一个 IPO 示例,用来计算矩形的面积:
# rectangle_area.py
# Calculate the area of a rectangle
# Formula: Area = length × width
print("Rectangle Area Calculator")
print("=" * 30)
print()
# INPUT: Get dimensions from user
length = float(input("Enter the length: "))
width = float(input("Enter the width: "))
# PROCESS: Calculate area
area = length * width
# OUTPUT: Display the result
print()
print("A rectangle with length", length, "and width", width)
print("has an area of", area, "square units")示例交互:
Rectangle Area Calculator
==============================
Enter the length: 5.5
Enter the width: 3.2
A rectangle with length 5.5 and width 3.2
has an area of 17.6 square units2.5.3) 示例:购物总额计算器
这个例子计算含税的购物总额:
# shopping_total.py
# Calculate total cost including tax
print("Shopping Total Calculator")
print("=" * 30)
print()
# INPUT: Get price and tax rate
price = float(input("Enter item price: $"))
tax_rate = float(input("Enter tax rate (as decimal, e.g., 0.08 for 8%): "))
# PROCESS: Calculate tax and total
tax_amount = price * tax_rate
total = price + tax_amount
# OUTPUT: Display itemized breakdown
# Note: Comma in print() adds a space after $
print()
print("Purchase Summary")
print("-" * 30)
print("Item price: $", price)
print("Tax rate: ", tax_rate * 100, "%")
print("Tax amount: $", tax_amount)
print("-" * 30)
print("Total: $", total)示例交互:
Shopping Total Calculator
==============================
Enter item price: $49.99
Enter tax rate (as decimal, e.g., 0.08 for 8%): 0.08
Purchase Summary
------------------------------
Item price: $ 49.99
Tax rate: 8.0 %
Tax amount: $ 3.9992
------------------------------
Total: $ 53.98922.6) 通过阅读简单错误信息进行基础调试
即便是经验丰富的程序员也会犯错。学会阅读和理解错误信息是一项重要技能,它能为你节省无数时间和挫败感。Python 的错误信息其实非常有帮助——它会告诉你哪里出错了,以及问题发生在什么位置。
术语“错误信息”(error message)和“回溯”(traceback)相关但略有不同:回溯是 Python 在出错时显示的完整报告,包括错误类型、描述,以及导致错误发生的代码路径。错误信息则是回溯最后一行,用来描述出了什么问题。在日常交流中,程序员常常用“错误信息”来泛指整个回溯。
2.6.1) 理解错误信息
当 Python 遇到错误时,会显示一段回溯——一份详细说明问题所在的报告。我们来看一个简单例子:
# error_example.py
print("Starting the program")
print("This line works fine"
print("This line might not be reached")当你尝试运行它时,Python 会显示:
File "error_example.py", line 2
print("This line works fine"
^
SyntaxError: '(' was never closed我们来分解一下这条错误信息告诉了我们什么:
- 文件名:
error_example.py—— 出错的文件 - 行号:
line 2—— Python 检测到问题的位置 - 代码片段:展示有问题的那一行,并用
^指出 Python 注意到问题的大致位置 - 错误类型:
SyntaxError—— 出错的种类 - 描述:
'(' was never closed—— 一段可读性较好的解释
错误发生的原因是我们在第 2 行忘记写右括号。Python 尝试把下一行也当作同一个 print() 语句的一部分来读取,于是就糊涂了。
2.6.2) 初学者常见错误类型
下面我们来看看你最常遇到的一些错误以及如何修复它们。
SyntaxError: Invalid Syntax
这是初学者最常见的错误。它表示 Python 无法理解你的代码,因为它不符合 Python 的语法规则。
缺少冒号:
# missing_colon.py
name = input("What is your name? ")
if name == "Alice" # Missing colon
print("Hello, Alice!")错误:
File "missing_colon.py", line 2
if name == "Alice"
^
SyntaxError: expected ':'注意:我们还没有学习 if 语句——将在第 8 章讲解。这个例子只是为了展示错误长什么样。
引号不匹配:
# mismatched_quotes.py
message = "Hello, world!'
print(message)错误:
File "mismatched_quotes.py", line 1
message = "Hello, world!'
^
SyntaxError: unterminated string literal (detected at line 1)错误的原因是字符串以双引号(")开始,却以单引号(')结束。Python 期望使用同一种引号作为开头和结尾。
NameError: Name Not Defined
当你尝试使用一个不存在的变量时,就会出现这个错误:
# name_error.py
print("Starting calculation")
result = total + 10 # 'total' was never created
print(result)错误:
Traceback (most recent call last):
File "name_error.py", line 2, in <module>
result = total + 10
^^^^^
NameError: name 'total' is not definedPython 告诉你它不知道 total 是什么,因为你从未创建过这个变量。修复方法是先定义 total 再使用它:
# name_error_fixed.py
print("Starting calculation")
total = 0 # Define the variable first
result = total + 10
print(result)导致 NameError 的常见原因:
- 变量名拼写错误(如
totla而不是total) - 在为变量赋值前就使用它
- 完全忘记创建变量
TypeError: Unsupported Operand Type(s)
当你试图对不兼容的类型执行某个操作时,就会出现这个错误:
# type_error.py
age = input("How old are you? ")
next_year = age + 1 # Can't add a number to a string
print("Next year:", next_year)错误:
Traceback (most recent call last):
File "type_error.py", line 2, in <module>
next_year = age + 1
~~~~^~~
TypeError: can only concatenate str (not "int") to strPython 告诉你,age 是字符串(因为 input() 返回字符串),你不能把数字加到字符串上。修复办法是把输入转换为整数:
# type_error_fixed.py
age = int(input("How old are you? ")) # Convert to integer
next_year = age + 1
print("Next year:", next_year)ValueError: Invalid Literal
当你尝试把字符串转换成数字,但该字符串并不是一个合法数字时,就会出现这个错误:
# value_error.py
age = int(input("How old are you? "))
print("You are", age, "years old")如果用户输入的是文本而不是数字:
How old are you? twenty
Traceback (most recent call last):
File "value_error.py", line 1, in <module>
age = int(input("How old are you? "))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'twenty'Python 告诉你,它无法把字符串 "twenty" 转换成整数。用户需要输入像 20 这样的数字。
重要说明:目前,如果用户输入了无效数据,你的程序就会因为错误而崩溃。对于初学者程序来说,这是正常的。在第 27 章,我们将学习如何使用异常处理(exception handling)优雅地处理这些情况,让程序能够从错误中恢复并要求用户重新输入。
2.6.3) 仔细阅读回溯
当程序出错时,Python 会显示一段回溯,用来追踪错误在你的代码中是如何产生的。对于简单程序,回溯会比较短:
# simple_traceback.py
print("Starting program")
name = input("Enter your name: ")
age = int(input("Enter your age: "))
print("Hello,", name)
print("Next year you'll be", age + 1)如果用户在输入年龄时输入了无效内容:
Starting program
Enter your name: Alice
Enter your age: abc
Traceback (most recent call last):
File "simple_traceback.py", line 3, in <module>
age = int(input("Enter your age: "))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'abc'这段回溯显示了:
- 出错的文件名和行号
- 导致问题的那一行代码
- 错误类型以及描述
阅读策略:从回溯的底部往上看。最后一行告诉你出了什么问题。上面的几行则告诉你错误发生在代码的什么位置。
2.6.4) 常见调试策略
当你遇到错误时,可以按以下步骤来处理:
1. 仔细阅读错误信息
不要慌!错误信息是在尝试帮助你。完整阅读它,并尝试理解它在说什么。
2. 查看行号
错误信息会告诉你 Python 认为哪一行有问题。不过,有时真正的错误出在上一行。例如,第 2 行缺少右括号,Python 可能要读到第 3 行才发现问题。
3. 检查常见错误
- 引号缺失或不匹配
- 缺少右括号或右中括号
- 缺少冒号(针对我们之后会学习的语句,如
if、for、while) - 变量名拼写错误
- 忘记把输入转换成数字
4. 使用 print() 检查值
如果你不确定问题出在哪里,可以添加一些 print() 语句,看看变量中存的是什么值:
# debugging_with_print.py
price = input("Enter price: ")
print("DEBUG: price =", price, "type =", type(price)) # Debugging line
tax = price * 0.08 # This will cause an error
print("Tax:", tax)这个调试输出告诉你 price 是字符串而不是数字,从而帮助你识别问题。
5. 注释掉代码以定位问题
如果代码有多行,而你不确定是哪一行导致错误,可以把一些行注释掉,直到错误消失:
# isolating_error.py
name = input("Enter name: ")
# age = int(input("Enter age: ")) # Commented out for testing
# city = input("Enter city: ") # Commented out for testing
print("Name:", name)一旦错误消失,你就知道问题出在被注释的某一行中。
6. 从简单版本开始
如果你的程序运行不正常,可以把它简化到最基本的形式:
# simplified_version.py
# Start with just the basic structure
print("Program starting")
# Add one feature at a time and test当简单版本正常运行后,再逐个添加功能,每加一个就测试一次。
2.6.5) 预防错误
虽然调试很重要,但从一开始就尽量避免错误会更好:
增量式编写代码
不要一次性写完整个程序然后再首次运行它。写几行代码,运行一下,确认这几行正常工作,然后再继续添加。这样,当出现错误时,你就知道问题出在刚刚添加的代码中。
# incremental_development.py
# Step 1: Get input and test
name = input("Enter name: ")
print("DEBUG: Got name:", name)
# Step 2: Add more input and test
# age = int(input("Enter age: "))
# print("DEBUG: Got age:", age)
# Step 3: Add processing and test
# ... and so on使用描述性变量名
清晰的变量名有助于避免错误:
# Clear variable names make errors less likely
user_age = int(input("Enter your age: "))
next_year_age = user_age + 1添加注释解释你的逻辑
注释可以帮助你(以及他人)理解代码“应该”做什么,从而更容易发现它实际做的事情什么时候不对:
# temperature_with_comments.py
# Get temperature in Fahrenheit from user
fahrenheit = float(input("Enter temperature in Fahrenheit: "))
# Convert to Celsius using the standard formula: C = (F - 32) × 5/9
celsius = (fahrenheit - 32) * 5 / 9
# Display the result
print(fahrenheit, "°F =", celsius, "°C")用不同输入值进行测试
不要只测试一次程序。尝试不同的输入,包括一些边界情况:
- 正常值:
25、100 - 零:
0 - 负数:
-10 - 小数:
3.14 - 非常大的数:
1000000
这有助于在用户遇到问题之前就发现它们。
2.6.6) 什么时候该求助他人
有时你会遇到自己解决不了的错误。在求助之前:
- 仔细阅读错误信息——确保你真的理解了它在说什么
- 搜索错误信息——复制错误信息(去掉你自己的变量名)并在网上搜索。许多错误都已经被别人遇到并解决过
- 仔细检查你的代码——查找拼写错误、缺失的标点以及常见错误
- 创建一个最小示例——将代码缩减到仍然能产生该错误的最小版本
当你真正去求助时,请提供:
- 完整的错误信息
- 能产生该错误的代码
- 你本来期望发生什么
- 实际发生了什么
- 你已经尝试过哪些方法
请记住:错误是编程中的正常组成部分。从初学者到专家,每个程序员每天都会遇到错误。不同之处在于,经验丰富的程序员学会了如何高效地阅读错误信息,并掌握了常见的解决办法。通过练习,你也会逐渐掌握这些技能。
你现在已经学习了 Python 编程的基本构建块:使用 print() 显示输出,用注释记录代码,用变量存储数据,用 input() 获取用户输入,遵循输入-处理-输出模式,以及调试简单错误。
这些概念构成了你之后学习所有 Python 内容的基础。在下一章中,我们将更深入地探讨变量,并研究 Python 的基本数据类型,帮助你更完整地理解 Python 如何存储和处理不同类型的信息。
本章要点总结:
- 使用
print()向用户显示文本和其他信息 - 使用注释(
#)解释代码并记录你的思路 - 使用赋值(
=)把数据存储在变量中 - 使用
input()获取用户输入,并在需要时将其转换为数字 - 使用输入-处理-输出模式来组织程序结构
- 仔细阅读错误信息——它们是在帮助你修复问题
- 以增量方式编写代码并频繁测试,以尽早发现错误
掌握了这些技能后,你已经能够编写简单但完整的交互式程序。随着学习的深入,你会在这些基础之上构建出越来越复杂的应用程序。