第1章 程序设计基础
1.1 程序的概念
什么是程序?
程序是一组指示计算机执行特定任务或操作的指令序列。计算机通过逐条执行这些指令,完成从输入数据到输出结果的整个处理过程。
通俗地说,程序就是"告诉计算机做什么以及怎么做"的一组命令。
生活中的类比
为了帮助你更好地理解"程序"这个概念,我们来看几个生活中的例子:
| 生活概念 | 类比说明 |
|---|---|
| 菜谱 | 菜谱是一系列步骤:洗菜→切菜→热油→炒菜→加调料→出锅。按照这个步骤执行,就能做出一道菜。程序也是类似的指令序列。 |
| 流程单/操作手册 | 工厂里的操作手册写明每一步该做什么:打开电源→按下启动键→等待3分钟→检查指示灯。操作员按手册执行就能完成任务。 |
| 说明书 | 组装家具的说明书用图文告诉你先组装A部件,再连接B部件,最后拧紧螺丝。这就是一组"指令序列"。 |
程序和这些生活类比一样,核心都是:按顺序执行一系列明确的步骤,最终得到一个结果。
程序是如何被计算机执行的?
计算机执行程序的过程可以简化为三个步骤的循环:
取指令 → 译码 → 执行 → 取下一条指令 → 译码 → 执行 → ...
- 取指令(Fetch):CPU从内存中读取一条程序指令
- 译码(Decode):CPU分析这条指令,理解要做什么(是加法运算,还是读取数据?)
- 执行(Execute):CPU实际执行该指令(如完成两个数字相加)
这个过程每秒钟重复数十亿次,这就是为什么计算机看起来"瞬间"完成了复杂的任务。
程序 vs 软件
这两个概念经常被混用,但严格来说:
- 程序(Program):一段具体的代码或指令集合,是软件的组成部分。一个程序可以只有几十行代码,完成一个简单的功能。
- 软件(Software):由多个程序、文档、配置等组成的完整产品。例如"微信"是一个软件,它内部包含了很多程序(聊天程序、支付程序、朋友圈程序等)。
简单记忆:程序是软件的"零件",软件是程序的"集合"。
最简单的程序示例
下面是一个用Python写的极简程序:
python
# 第一个程序:向世界问好
print("你好,世界!")
这个程序只有一条指令,告诉计算机在屏幕上显示"你好,世界!"这几个字。
再看一个稍微复杂一点的例子:
python
# 第二个程序:打招呼
name = "小明"
print(name + ",欢迎来到Python的世界!")
这个程序由两条指令组成:第一条将名字"小明"存储在变量中,第二条利用这个变量输出一句完整的问候语。
关键理解:程序就是一系列这样的指令,从简单到复杂,组合起来完成各种各样的任务。
1.2 算法的五个特征
算法(Algorithm) 是指解决问题的一系列清晰、确定的步骤。任何一个合格的算法都必须同时具备以下五个特征。
五个特征逐个讲解
1. 有穷性(Finiteness)
定义:算法必须在执行有限步之后终止,不能无限循环下去。
生活化例子:
- 正确例子:"煮方便面"的步骤:烧水→放面→泡3分钟→开吃。总共4步,步骤有限。
- 错误例子:"继续烧水直到水烧干"------如果永远不关火,水会一直烧下去,永远不会结束。这不是一个好算法,因为它不满足有穷性。
在编程中,这意味着循环必须有终止条件。例如 while True: 如果不写 break,就会无限循环。
2. 确定性(Definiteness)
定义:算法的每一步必须有确切的含义,不能有歧义。
生活化例子:
- 正确例子:"将西红柿切成2厘米见方的小块"------尺寸明确,不会产生歧义。
- 错误例子:"放少许盐"------"少许"是多少?1克还是10克?不同的人有不同的理解,这就是歧义。
在编程中,每一步操作都必须是明确无误的。例如 x = x + 1 的含义是确定的:把x当前的值加1后再赋给x。而"把x变大一点"是无法被计算机执行的,因为它不确定。
3. 可行性(Feasibility)
定义:算法的每一步都必须是可行的,能够通过基本操作来实现。
生活化例子:
- 正确例子:"步行100米到公交站"------这是可以做到的。
- 错误例子:"一步跨过100米宽的河"------这超出了正常人的能力,不可行。
在编程中,这意味着算法中的每个操作都必须是计算机能够实际执行的基本操作。例如"计算1+1"是可行的,但"计算出宇宙中所有原子的精确数量"在当前条件下是不可行的。
4. 输入(Input)
定义:算法可以有零个或多个输入。
生活化例子:
- 有输入:"计算圆的面积"------需要输入半径r
- 零输入:"输出100以内的素数"------不需要外部输入,算法自身就能完成
理解:输入是算法从外部获取的数据。零输入意味着算法不需要外部数据,自己就能运行。这一点常被误解------很多人以为算法必须有输入,但实际上是可以为零的。
5. 输出(Output)
定义:算法有一个或多个输出。
生活化例子:
- 正确例子:"求两个数的最大值"------输出那个较大的数
- 没有输出的例子:"计算了总分但不告诉任何人"------这种"计算"没有意义
重要提醒 :算法必须至少有一个输出。没有输出的算法是毫无意义的------如果做完计算却不给出结果,那为什么要执行呢?
好算法 vs 坏算法
| 对比维度 | 好算法 | 坏算法 |
|---|---|---|
| 速度 | 执行步骤少、效率高(如用公式直接求面积) | 步骤冗余、效率低(如用数格子的方式求面积) |
| 可读性 | 思路清晰,别人容易理解 | 逻辑混乱,难以看懂 |
| 通用性 | 能处理各种边界情况(如输入为负数、为零等) | 只考虑理想情况,遇到特殊情况就出错 |
| 资源消耗 | 占用内存少、CPU时间短 | 浪费大量内存或CPU时间 |
举例对比:求1到100的和
- 好算法 :用等差数列求和公式
(1+100)*100/2 = 5050,只需要3步计算 - 坏算法 :
1+2+3+...+100,需要99步加法,效率低得多
算法示例:找最大数
下面是一个简单算法的步骤描述,让你感受算法的表达方式:
问题:找出三个数 a, b, c 中的最大值
算法步骤:
第一步:将 a 赋值给变量 max(假设a是最大的)
第二步:如果 b > max,则将 b 赋值给 max
第三步:如果 c > max,则将 c 赋值给 max
第四步:输出 max
这个算法思路清晰、步骤有限、每步确定可行,并且有输入(a, b, c)和输出(max),具备了算法的全部五个特征。
算法与程序的关系
算法是思路,程序是算法的代码实现。
- 算法:解决问题的思路和步骤,可以用自然语言、流程图或伪代码来描述。算法不依赖任何编程语言。
- 程序:将算法的每一步用某种编程语言(如Python)写出来的具体代码。
举个例子:
算法思路(找最大数):
先假设第一个最大,然后依次与后面的数比较
对应的Python程序:
a, b, c = 5, 9, 3
max_val = a
if b > max_val:
max_val = b
if c > max_val:
max_val = c
print("最大数是:", max_val)
核心要点:同一个算法可以用不同的编程语言来实现。关键是先想清楚"怎么做"(算法),再动手写代码(程序)。
算法设计的要求
除了具备上述五个基本特征外,一个好的算法还应该满足以下四个设计要求:
1. 正确性(Correctness)
算法必须能够正确地解决它所要处理的问题。这是最基本、最重要的要求。
- 算法应该对所有合法的输入都能产生正确的输出
- 不能只在部分情况下正确,而在边界情况或特殊情况出错
- 例如:一个排序算法不仅要对
[3, 1, 2]排序正确,对空列表、只有一个元素的列表、含重复元素的列表也要正确处理
2. 可读性(Readability)
算法应该容易被人阅读和理解。
- 代码清晰、结构明了、有适当的注释
- 可读性好的算法便于调试、维护和团队协作
- 晦涩难懂的算法即使效率再高,也难以长期维护
- 这也是为什么我们强调变量名要"见名知意"、代码要加注释的原因
3. 健壮性(Robustness)
算法应具备处理异常情况的能力,也称"容错性"。
- 当输入数据非法时(如除数为零、输入非数字字符),算法应能作出适当处理,而不是崩溃
- 好的算法能对意外情况给出友好的提示或合理的处理方案
- 例如:除法运算前应先检查除数是否为零,而不是让程序报错退出
4. 高效率与低存储量要求(Efficiency & Low Storage)
算法应尽量少地占用计算时间和存储空间。
- 时间复杂度:算法执行花费的时间应尽可能短
- 空间复杂度:算法占用的内存空间应尽可能小
- 两者往往需要折中权衡------有时用空间换时间,有时用时间换空间
- 例如前面提到的"求1到100的和",用公式
(1+100)*100/2只要1步,而循环累加需要99步,公式法效率更高
| 设计要求 | 核心问题 | 生活类比 |
|---|---|---|
| 正确性 | 结果对吗? | 菜谱步骤正确,做出来的菜能吃 |
| 可读性 | 别人能看懂吗? | 菜谱写得清楚,别人也能照着做 |
| 健壮性 | 遇到意外能处理吗? | 突然没盐了,有替代方案 |
| 高效率 | 够快、够省吗? | 用最短时间、最少材料做出菜 |
1.3 程序设计语言的发展
程序设计语言的发展经历了三个主要阶段,从最底层的机器语言逐步进化到接近人类自然语言的高级语言。
机器语言 → 汇编语言 → 高级语言
(第一代) (第二代) (第三代及以上)
1.3.1 机器语言(第一代)
为什么计算机只懂0和1?
计算机的核心是CPU(中央处理器),CPU内部由数以亿计的微型开关电路(晶体管)组成。每个晶体管只有两种状态:
- 通电 (高电压)→ 表示 1
- 断电 (低电压)→ 表示 0
计算机内部所有的数据和指令,最终都以这种"通电/断电"的二进制形式存在。就像用开关控制电灯一样------开关打开(1)灯亮,开关关闭(0)灯灭。数亿个这样的开关组合起来,就能表示和处理各种复杂的信息。
机器语言的特点:
- 由二进制代码(0和1)组成,如
10110000 01100001 - 计算机CPU可以直接识别和执行,不需要翻译
- 优点:执行效率最高,因为是计算机"原生"的语言
- 缺点 :
- 编写极其困难,容易出错
- 可读性几乎为零,很难看懂代码在做什么
- 完全依赖硬件,不同型号的CPU指令集不同,无法移植
在计算机早期,程序员需要直接写二进制代码编程,效率极低。这就催生了汇编语言的出现。
1.3.2 汇编语言(第二代)
汇编语言用**助记符(Mnemonic)**代替二进制指令,让编程变得稍微人性化了一些。
| 机器指令(二进制) | 汇编助记符 | 含义 |
|---|---|---|
10110000 01100001 |
MOV AL, 61H |
将十六进制数61(即字母'a')存入寄存器AL |
00000100 00000001 |
ADD AL, 1 |
将寄存器AL的值加1 |
有了助记符,程序员不再需要记忆一串0和1,而是可以用 MOV、ADD、SUB、JMP 等有意义的英文缩写来编写程序。
汇编语言的特点:
- 需要通过**汇编程序(Assembler)**翻译成机器语言才能执行
- 优点:比机器语言易读,执行效率也很高
- 缺点:仍然依赖具体的CPU型号,不同架构的CPU(如x86和ARM)指令集不同
1.3.3 高级语言(第三代及以上)
高级语言更加接近人类自然语言和数学表达方式,大大降低了编程的门槛。
示例对比(完成"Hello World"输出):
| 语言 | 代码 |
|---|---|
| 机器语言 | 10110000 ...(大量二进制代码) |
| 汇编语言 | MOV DX, OFFSET msg 等多条指令 |
| Python | print("Hello") |
| Java | System.out.println("Hello"); |
可以看到,高级语言的表达方式几乎就是自然语言,学习成本大大降低。
编译型语言 vs 解释型语言
高级语言必须转换成机器语言才能被计算机执行。根据转换方式的不同,分为编译型和解释型两大类。
| 对比维度 | 编译型语言 | 解释型语言 |
|---|---|---|
| 代表语言 | C、C++、Go | Python、JavaScript、Ruby |
| 执行方式 | 用编译器一次性将源码全部翻译成机器码,生成独立的可执行文件(.exe等) | 用解释器逐行读取源代码,边翻译边执行 |
| 执行速度 | 快(已提前翻译好) | 相对较慢(每次运行都要逐行翻译) |
| 开发效率 | 较低(修改代码后需要重新编译才能运行) | 较高(修改后立即运行,无需编译) |
| 可移植性 | 编译后的可执行文件通常只能在特定平台运行 | 只要有对应平台的解释器,源码可直接运行 |
| 典型流程 | 源码 → 编译器 → 可执行文件 → 运行 | 源码 → 解释器(逐行翻译并执行) |
简单记忆:
- 编译型就像翻译一本书:把整本书一次性翻译成中文,以后直接看中文版
- 解释型就像同声传译:每说一句话,翻译立刻译成另一语言
Python 为什么是解释型语言?
Python是一种解释型语言 ,它通过 Python解释器 逐行读取并执行代码。
逐行执行的优缺点:
| 优点 | 缺点 |
|---|---|
| 编写后立即运行,无需编译,调试方便 | 执行速度相对编译型语言慢一些 |
| 交互式编程(IDLE中一行一行测试) | 不适合对性能要求极高的场景(如操作系统内核) |
| 跨平台性好,任何安装了Python解释器的系统都能运行 | 源码直接暴露,无法像编译型那样保护源代码 |
| 适合快速开发和原型设计 | 大型项目运行效率不如C++ |
Python版本简史
Python由Guido van Rossum(吉多·范罗苏姆)于1989年圣诞节期间开始设计,1991年首次发布。
- Python 2.x(2000年发布):曾经广泛使用,但已于2020年1月1日正式停止维护
- Python 3.x(2008年发布):当前主流版本,不兼容Python 2
Python 2 vs Python 3 的主要区别(简单了解即可):
| 区别 | Python 2 | Python 3 |
|---|---|---|
| 输出语句 | print "Hello"(语句) |
print("Hello")(函数) |
| 整数除法 | 5/2 = 2(整数除法) |
5/2 = 2.5(浮点除法) |
| 字符串编码 | 默认ASCII | 默认Unicode(支持中文更好) |
| 输入函数 | raw_input() |
input() |
当前务必使用Python 3,Python 2已经退出历史舞台。
1.4 IPO模式
IPO是程序设计中最基础、最普遍的一种模式,代表三个核心环节:Input(输入) → Process(处理) → Output(输出)。
什么是IPO模式?
任何程序都可以抽象为IPO模式,其基本结构如下:
+----------------+ +------------------+ +----------------+
| Input (输入) | --> | Process (处理) | --> | Output (输出) |
| 获取外部数据 | | 运算和处理数据 | | 呈现处理结果 |
+----------------+ +------------------+ +----------------+
- 输入(Input):程序从外部获取数据的过程
- 处理(Process):对输入的数据进行运算、判断、变换等操作
- 输出(Output):将处理结果以某种形式呈现给用户或保存到外部
生活中的IPO例子
| 场景 | 输入(Input) | 处理(Process) | 输出(Output) |
|---|---|---|---|
| 自动售货机 | 投币 + 选择商品编号 | 检查金额是否足够 → 计算找零 → 释放商品 | 出货 + 找零 |
| 银行ATM取款 | 插卡 + 输入密码 + 输入金额 | 验证密码 → 检查余额 → 扣减余额 | 出钞 + 打印凭条 |
| 电子秤 | 放置商品(压力传感器获取重量) | 重量 × 单价 = 总价 | 显示金额 |
| 天气预报APP | 获取GPS位置 + 请求气象数据 | 解析数据 → 生成预报图表 | 显示天气信息 |
这些场景虽然完全不同,但都可以用IPO模式来分析:先有什么输入,然后做什么处理,最后输出什么结果。
用Python代码展示IPO三环节
下面用代码展示IPO三个环节在Python中的具体写法:
输入(Input)环节
python
# 最常见的输入方式:通过键盘输入
name = input("请输入你的姓名:") # 输入字符串
age = int(input("请输入你的年龄:")) # 输入后转为整数
height = float(input("请输入身高:")) # 输入后转为浮点数
处理(Process)环节
python
# 处理环节:对输入的数据进行各种运算和操作
# 数学运算
total = 85 + 92 # 加法
average = total / 2 # 除法
discount_price = price * 0.8 # 乘法(打8折)
# 条件判断
if age >= 18:
status = "成年人"
else:
status = "未成年人"
# 循环处理
sum_val = 0
for i in range(1, 101):
sum_val = sum_val + i # 1加到100
输出(Output)环节
python
# 最常见的输出方式:在屏幕显示
print("你好,Python!") # 输出字符串
print("总分:", total) # 输出变量值
print(f"平均分:{average}") # f-string格式化输出
IPO完整示例:计算圆的面积
python
# 输入
radius = float(input("请输入圆的半径:"))
# 处理
pi = 3.14159
area = pi * radius * radius
# 输出
print(f"半径为{radius}的圆,面积为:{area}")
这个程序清晰地分为三部分:读取用户输入的半径 → 用公式计算面积 → 显示结果。
如何用IPO思维拆解实际问题?
面对一个编程题目时,可以按照以下三个问题来思考:
第一步:输入是什么?
- 用户会给我什么数据?(键盘输入、文件读取、传感器数据等)
- 数据是什么类型?(数字、文字、还是其他)
第二步:处理要做什么?
- 要对输入的数据做什么运算?(加减乘除、比较大小、筛选过滤等)
- 需要什么公式或逻辑?
第三步:输出是什么?
- 最终要给用户呈现什么结果?(屏幕显示、保存文件、还是控制设备)
实战示例:编写一个"温度转换"程序
用IPO思维拆解:
| 环节 | 分析结果 |
|---|---|
| 输入 | 用户输入一个摄氏温度值 |
| 处理 | 使用转换公式:华氏温度 = 摄氏温度 × 9/5 + 32 |
| 输出 | 显示对应的华氏温度值 |
python
# 温度转换程序
celsius = float(input("请输入摄氏温度:")) # 输入
fahrenheit = celsius * 9 / 5 + 32 # 处理
print(f"对应的华氏温度为:{fahrenheit}°F") # 输出
按照这个思路,任何编程问题都可以先拆解为IPO三个环节,然后再逐个实现。
IPO模式 vs 面向过程
IPO模式实际上是一种面向过程的编程思维------它关注的是"数据如何流动"以及"每一步要做什么处理"。
两者的关系:
- 面向过程编程:以"过程/函数"为核心,强调程序执行的步骤和顺序。IPO就是面向过程的一种典型结构。
- IPO模式:是面向过程编程的一种具体表现形式,特别适合初学者理解程序的基本构成。
当你后续学习更多编程知识后,你会发现很多程序都可以看作是IPO的扩展和组合------一个程序的输出可能是另一个程序的输入,多个IPO环节串联起来就构成了复杂的系统。
1.5 面向对象编程(OOP)基本概念
面向对象编程(Object-Oriented Programming, OOP) 是一种以"对象"为中心的编程思想。Python不仅支持面向过程编程,也支持面向对象编程。
面向过程 vs 面向对象
在深入了解OOP之前,先对比两种编程思想:
| 对比维度 | 面向过程编程 | 面向对象编程 |
|---|---|---|
| 核心关注点 | 做什么步骤(过程) | 谁来做(对象) |
| 组织方式 | 按功能拆分为函数 | 按现实事物抽象为类和对象 |
| 典型思维 | 先做什么,再做什么,最后做什么 | 有哪些对象,每个对象有什么属性和行为 |
| 生活类比 | 菜谱(按步骤做菜) | 餐厅(厨师、服务员、顾客各自分工) |
| 适用场景 | 简单、线性的任务 | 复杂、多角色交互的系统 |
简单来说:
- 面向过程:关心"怎么做"(步骤)
- 面向对象:关心"谁来做"(对象)
核心概念详解
1. 类(Class)------ 对象的"蓝图"
类是具有相同属性和方法的一类事物的抽象模板。
生活类比:"学生"是一个类。所有学生都有共同特征(有姓名、有学号、会学习),但"学生"本身不是一个具体的人,而是对这类人的概括描述。
Python示意代码:
python
# 定义一个"学生"类
class Student:
def __init__(self, name, student_id):
self.name = name # 属性:姓名
self.student_id = student_id # 属性:学号
def study(self, course): # 方法:学习
print(f"{self.name}正在学习{course}")
关键理解:类就像一张建筑设计图纸------图纸本身不是房子,但可以根据图纸建造出很多具体的房子。
2. 对象(Object)------ 类的具体实例
对象是根据类创建出来的具体实体。
生活类比:"张三"是"学生"类的一个具体对象。张三有具体的姓名(张三)、具体的学号(2024001),他真的会去学习。
Python示意代码:
python
# 根据Student类创建两个具体的学生对象
zhangsan = Student("张三", "2024001")
lisi = Student("李四", "2024002")
# 调用对象的方法
zhangsan.study("Python程序设计") # 输出:张三正在学习Python程序设计
关键理解:类是抽象的概念,对象是具体的存在。从同一个类可以创建出多个不同的对象(就像从同一张设计图可以建造出多栋房子)。
3. 封装(Encapsulation)------ 隐藏内部细节
封装是将数据(属性)和操作数据的方法捆绑在一起,对外部隐藏内部实现细节。
生活类比:手机的外壳把内部复杂的电路板、芯片等封装起来。你只需要按按钮、触摸屏幕就能使用手机,而不需要知道内部电路是如何工作的。
Python示意代码:
python
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance # 私有属性(两个下划线开头)
def deposit(self, amount): # 公开方法:存款
if amount > 0:
self.__balance += amount
def get_balance(self): # 公开方法:查询余额
return self.__balance
# 使用封装好的类
account = BankAccount("张三", 1000)
account.deposit(500) # 通过公开方法操作
print(account.get_balance()) # 输出:1500
# print(account.__balance) # 错误!不能直接访问私有属性
封装的好处:
- 保护数据不被外部随意修改
- 降低使用复杂度------使用者只需要知道公开的方法,不需要了解内部实现
4. 继承(Inheritance)------ 复用已有的代码
继承是子类自动拥有父类的属性和方法,并可以在此基础上增加自己的新特性。
生活类比:"大学生"继承了"学生"的所有特征(有姓名、有学号、会学习),同时增加了自己的新特征(有专业、有导师)。
Python示意代码:
python
# 父类(基类)
class Student:
def __init__(self, name):
self.name = name
def introduce(self):
print(f"我叫{self.name}")
# 子类(派生类):继承了Student的所有属性和方法
class CollegeStudent(Student):
def __init__(self, name, major):
super().__init__(name) # 调用父类的初始化方法
self.major = major # 新增属性:专业
def study_major(self): # 新增方法:学习专业课
print(f"{self.name}正在学习{self.major}专业课程")
# 使用
s = CollegeStudent("张三", "计算机科学")
s.introduce() # 继承的方法 输出:我叫张三
s.study_major() # 自己的方法 输出:张三正在学习计算机科学专业课程
继承的好处:
- 代码复用:子类不用重新写父类已有的代码
- 层次清晰:体现了"一般→特殊"的分类关系
- 易于扩展:可以在不修改父类的情况下增加新功能
5. 多态(Polymorphism)------ 同一个接口,不同行为
多态是指同一个方法名在不同类的对象上表现出不同的行为。
生活类比:同样执行"叫"这个动作,猫发出"喵",狗发出"汪"。动作名称相同(叫),但具体行为不同。
Python示意代码:
python
class Cat:
def sound(self):
print("喵喵~")
class Dog:
def sound(self):
print("汪汪!")
# 多态的体现:同一个方法名,不同对象不同行为
animals = [Cat(), Dog()]
for animal in animals:
animal.sound()
# 输出:
# 喵喵~
# 汪汪!
多态的好处:
- 统一接口:可以用相同的调用方式处理不同类型的对象
- 灵活扩展:新增类时,只要保证有相同的方法名,现有代码无需修改
OOP为什么重要?
面向对象编程之所以成为主流的编程思想,主要有以下几个原因:
-
贴近现实世界:OOP用"对象"来模拟现实中的事物,使编程思维更自然。设计一个"学生管理系统",你会自然地想到"学生"、"课程"、"教师"这些对象。
-
便于团队协作:大型软件通常由多人开发。用OOP可以将系统拆分为相对独立的类和模块,不同开发者负责不同的类,互不干扰。
-
代码复用性高:通过继承和封装,已经写好的类可以被多次使用,减少重复劳动。
-
易于维护和扩展:修改一个类的内部实现,只要对外接口不变,就不会影响其他部分。新增功能可以通过添加新类或继承来实现。
Python中类和对象的简单示意
下面是一个完整的、简单的小示例,展示类和对象的配合使用:
python
# 定义一个"狗"类
class Dog:
def __init__(self, name, age):
self.name = name # 属性:名字
self.age = age # 属性:年龄
def bark(self): # 方法:叫
print(f"{self.name}说:汪汪!")
def introduce(self): # 方法:自我介绍
print(f"我是{self.name},今年{self.age}岁")
# 创建两个具体的狗对象
dog1 = Dog("旺财", 3)
dog2 = Dog("小白", 1)
# 让对象执行行为
dog1.introduce() # 输出:我是旺财,今年3岁
dog1.bark() # 输出:旺财说:汪汪!
dog2.introduce() # 输出:我是小白,今年1岁
这个例子展示了OOP的核心思想:
- 数据(属性)和行为(方法)被封装在一起
- 从同一个类可以创建多个不同的对象
- 每个对象有自己的状态(不同的名字和年龄)
面向过程 vs 面向对象深入对比
前面我们初步对比了两种编程思想,下面从设计思路的角度进行更深入的比较,帮助你理解两种编程范式的本质差异。
面向过程编程的设计思路
面向过程编程的核心思路是:自顶向下、逐步求精、分而治之。
-
自顶向下(Top-Down):从整体问题出发,逐层分解为更小的子问题。比如写一个"学生成绩管理系统",先分为"录入成绩→计算统计→输出报表"三大步,再细分每步的具体逻辑。
-
逐步求精(Stepwise Refinement):每一步继续分解,直到每个小步骤都能直接用代码实现。比如"计算统计"这个步骤可以细分为"求总分→求平均分→求最高分→求最低分"。
-
分而治之(Divide and Conquer):把大问题拆成小问题,分别解决,再组合起来。
在面向过程程序中,模块内部通常使用三种基本结构来组织:
- 顺序结构:按先后顺序执行
- 选择结构:根据条件选择不同分支(if-else)
- 循环结构:重复执行某些步骤(for/while)
用函数实现模块化是面向过程的核心手段------每个函数完成一个独立的子功能。模块化设计追求的是:
- 高内聚(High Cohesion):一个模块内部的功能紧密相关,专注于做好一件事
- 低耦合(Low Coupling):模块之间的依赖关系尽量少,一个模块的修改不影响其他模块
面向对象编程的设计思路
面向对象编程的核心思路是:将数据和操作封装在一起,以对象为单位进行组织。
-
数据和操作封装在一起:一个对象既包含数据(属性),又包含操作这些数据的方法。比如"学生"对象既有姓名、成绩等属性,又有计算平均分、打印信息等方法。
-
抽象共性形成类:从多个具体对象中提取共同特征,形成一个类模板。比如张三、李四都是学生,他们有共同的属性(姓名、学号)和行为(学习、考试),于是抽象出"学生类"。
-
类通过外部接口通信:类对外暴露公开方法(接口),隐藏内部实现细节(封装)。外部代码只能通过这些公开接口与对象交互,而不能直接访问内部数据。
-
对象通过消息通信:一个对象调用另一个对象的方法,就像向它"发送消息"。对象接收到消息后,自行决定如何响应。
两者对比总结
| 对比维度 | 面向过程编程 | 面向对象编程 |
|---|---|---|
| 设计思路 | 自顶向下逐步求精、分而治之 | 抽象共性形成类、封装数据与操作 |
| 程序组成 | 函数(过程/子程序) | 类 和 对象 |
| 核心关注 | 做什么步骤(算法/流程) | 谁来做(对象/职责) |
| 数据与操作 | 数据与操作分离(数据传来传去) | 数据与操作封装在一起 |
| 模块化方式 | 函数实现模块化 | 类实现模块化 |
| 模块内部 | 三种基本结构(顺序/选择/循环) | 属性 + 方法 |
| 模块通信 | 函数调用、参数传递 | 对象通过消息(方法调用)通信 |
| 设计原则 | 高内聚、低耦合 | 单一职责、封装、继承、多态 |
| 优点 | 思路简单直接,适合小规模程序 | 安全性好、可重用性好、易维护、易扩展 |
| 生活类比 | 按菜谱做菜(一步步来) | 餐厅分工(厨师、服务员、收银各司其职) |
选择建议:对于较小的、流程明确的任务(如数学计算、文件处理),面向过程简洁高效;对于复杂的、多角色交互的系统(如游戏、管理系统),面向对象更能管理复杂度。Python同时支持两种编程方式,可以根据实际需求灵活选择。
第2章 Python语言基础
2.1 程序的基本结构
一个Python程序的基本结构包括以下要素:
- 注释 :以
#开头,对代码进行解释说明,不参与执行 - 输入语句 :通过
input()获取用户输入 - 处理语句:变量赋值、表达式计算、条件判断、循环等
- 输出语句 :通过
print()输出结果
python
name = input("请输入你的名字:") # 输入
greeting = "你好," + name # 处理
print(greeting) # 输出
2.2 数据类型
Python中最基本的数据类型有以下四种:
2.2.1 整数(int)
表示整数值,如 10、-3、0、1000000。
python
a = 10 # 正整数
b = -5 # 负整数
c = 0 # 零
2.2.2 浮点数(float)
表示带小数点的数值,如 3.14、-0.5、2.0。
python
# 浮点变量 pi = 3.14(带小数)
pi = 3.14
# 浮点变量 temp = -5.5(带小数)
temp = -5.5
# 浮点变量 score = 87.5(带小数)
score = 87.5
注意 :
2.0是浮点数,而2是整数,两者类型不同。
2.2.3 布尔值(bool)
只有两个值:True(真)和 False(假)。
python
# 布尔变量 is_student = True(真)
is_student = True
# 布尔变量 is_adult = False(假)
is_adult = False
布尔值通常用于条件判断中。
2.2.4 字符串(str)
用单引号 '' 或双引号 "" 括起来的文本。
python
# 字符串变量 name,存储文本
name = "张三"
# 字符串变量 city,存储文本
city = '北京'
# 字符串变量 empty_str,存储文本
empty_str = ""
查看数据类型
使用 type() 函数可以查看数据的类型:
python
print(type(10)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type(True)) # <class 'bool'>
print(type("Hello")) # <class 'str'>
2.3 变量命名规则
变量是存储数据的容器。给变量取名时必须遵守以下规则:
硬性规则(必须遵守)
- 由字母、数字、下划线组成,不能包含空格和特殊字符(如 @、#、$ 等)
- 不能以数字开头
- 不能是Python关键字(保留字)
- 区分大小写 (
name和Name是两个不同的变量)
Python关键字(不能用作变量名)
False, None, True, and, as, assert, async, await, break, class,
continue, def, del, elif, else, except, finally, for, from, global,
if, import, in, is, lambda, nonlocal, not, or, pass, raise, return,
try, while, with, yield
命名规范(建议遵守)
- 见名知意 :使用有意义的英文单词,如
score、name、total_price - 蛇形命名法(snake_case) :多个单词用下划线分隔,如
student_name、max_value
python
# 整型变量 age = 18
age = 18
# 字符串变量 student_name,存储文本
student_name = "李四"
# 整型变量 max_score = 100
max_score = 100
# 浮点变量 _temp = 25.5(带小数)
_temp = 25.5
2.3.1 链式赋值
链式赋值是指将同一个值同时赋给多个变量,写法简洁高效。
python
# 链式赋值:x、y、z 都被赋值为 200
x = y = z = 200 # 等价于 x=200; y=200; z=200
print(x) # 输出 200
print(y) # 输出 200
print(z) # 输出 200
注意 :链式赋值是从右向左 依次赋值的,
x = y = z = 200先把200赋给z,再把z的值赋给y,最后赋给x。
2.3.2 解包赋值(平行赋值)
解包赋值可以在一行内给多个变量分别赋予不同的值,等号两边用逗号分隔。
python
# 解包赋值:a 得到 1,b 得到 2
a, b = 1, 2
print(a) # 输出 1
print(b) # 输出 2
# 同时给三个变量赋值
name, age, score = "张三", 18, 95.5
print(name) # 输出 张三
print(age) # 输出 18
print(score) # 输出 95.5
解包赋值最经典的应用------两数交换:
传统方法需要借助第三个临时变量,而Python用解包赋值一行就能完成:
python
# 传统交换方法(需要临时变量)
a = 10
b = 20
temp = a # 暂存a的值
a = b # a得到b的值
b = temp # b得到原来a的值
# Python解包赋值的优雅写法(一行搞定)
a, b = 10, 20
a, b = b, a # 直接交换!
print(a) # 输出 20
print(b) # 输出 10
关键理解 :
a, b = b, a的执行过程是:先计算等号右边的(b, a)形成元组,再解包依次赋值给左边的a和b,所以不会出现数据覆盖的问题。
2.4 表达式和运算符
2.4.1 算术运算符
| 运算符 | 描述 | 示例 | 结果 |
|---|---|---|---|
+ |
加 | 5 + 3 |
8 |
- |
减 | 5 - 3 |
2 |
* |
乘 | 5 * 3 |
15 |
/ |
除(结果为浮点数) | 5 / 2 |
2.5 |
// |
整除(取商的整数部分) | 5 // 2 |
2 |
% |
取余(取余数) | 5 % 2 |
1 |
** |
幂运算 | 5 ** 2 |
25 |
注意 :
/的结果始终是浮点数,即使能整除(如4 / 2结果是2.0)。
2.4.2 字符串运算
| 运算符 | 描述 | 示例 | 结果 |
|---|---|---|---|
+ |
字符串拼接 | "Hello" + " " + "World" |
"Hello World" |
* |
字符串重复 | "Ha" * 3 |
"HaHaHa" |
2.4.3 关系(比较)运算符
| 运算符 | 描述 | 示例(设 a=5, b=3) | 结果 |
|---|---|---|---|
== |
等于 | a == b |
False |
!= |
不等于 | a != b |
True |
> |
大于 | a > b |
True |
< |
小于 | a < b |
False |
>= |
大于等于 | a >= b |
True |
<= |
小于等于 | a <= b |
False |
关系运算的结果是布尔值(True 或 False)。
2.4.4 逻辑运算符
| 运算符 | 描述 | 示例 | 结果 |
|---|---|---|---|
and |
逻辑与(两边都为True才为True) | True and False |
False |
or |
逻辑或(至少一边为True即为True) | True or False |
True |
not |
逻辑非(取反) | not True |
False |
逻辑运算符短路规则(常考):
a and b:如果a为False,则直接返回False,不再计算ba or b:如果a为True,则直接返回True,不再计算b
2.4.5 运算符优先级(从高到低)
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1 | () |
圆括号 |
| 2 | ** |
幂运算 |
| 3 | +x, -x |
一元正负号 |
| 4 | *, /, //, % |
乘、除、整除、取余 |
| 5 | +, - |
加、减 |
| 6 | ==, !=, >, <, >=, <= |
比较运算符 |
| 7 | not |
逻辑非 |
| 8 | and |
逻辑与 |
| 9 | or |
逻辑或 |
记忆技巧 :括幂乘除加减,比较not and or。同级运算从左到右执行。
示例
python
result = 2 + 3 * 4 ** 2 # 先算 4**2=16,再算 3*16=48,最后 2+48=50
print(result) # 输出 50
result2 = (2 + 3) * 4 # 括号优先级最高,先算 2+3=5,再算 5*4=20
print(result2) # 输出 20
result3 = 5 > 3 and 4 < 2 # 先算 5>3=True,4<2=False,再算 True and False=False
print(result3) # 输出 False
2.4.6 复合赋值运算符
复合赋值运算符将算术运算和赋值合二为一,让代码更简洁。
| 运算符 | 示例 | 等价于 | 说明 |
|---|---|---|---|
= |
a = 5 |
直接赋值 | 基本赋值 |
+= |
a += 3 |
a = a + 3 |
先加后赋值 |
-= |
a -= 3 |
a = a - 3 |
先减后赋值 |
*= |
a *= 3 |
a = a * 3 |
先乘后赋值 |
/= |
a /= 3 |
a = a / 3 |
先除后赋值 |
//= |
a //= 3 |
a = a // 3 |
先整除后赋值 |
%= |
a %= 3 |
a = a % 3 |
先取余后赋值 |
**= |
a **= 3 |
a = a ** 3 |
先幂运算后赋值 |
使用示例:
python
# 整型变量 total = 0
total = 0
# 累加操作
total += 10 # 等价于 total = total + 10,现在 total = 10
total += 5 # total = 15
# 整型变量 score = 100
score = 100
# 减法操作
score -= 20 # 等价于 score = score - 20,现在 score = 80
# 整型变量 count = 1
count = 1
# 乘法操作
count *= 5 # 等价于 count = count * 5,现在 count = 5
# 浮点变量 price = 100.0
price = 100.0
# 除法操作
price /= 3 # 等价于 price = price / 3,现在 price ≈ 33.333...
# 整数 整除
a = 10
a //= 3 # a = 10 // 3 = 3
# 取余
b = 10
b %= 3 # b = 10 % 3 = 1
# 幂运算
c = 2
c **= 4 # c = 2 ** 4 = 16
print(total, score, count, price, a, b, c)
# 输出: 15 80 5 33.333333333333336 3 1 16
考试注意 :
+=这类运算符是一个整体,中间不能有空格(+ =是错误的)。
2.5 内置函数
Python提供了丰富的内置函数,以下是本章常用的内置函数:
| 函数 | 功能 | 示例 |
|---|---|---|
print() |
输出到控制台 | print("Hello") |
input() |
从键盘获取输入(返回字符串) | name = input("姓名:") |
int() |
转换为整数 | int("123") → 123 |
float() |
转换为浮点数 | float("3.14") → 3.14 |
str() |
转换为字符串 | str(123) → "123" |
type() |
查看数据类型 | type(10) → <class 'int'> |
abs() |
取绝对值 | abs(-5) → 5 |
divmod() |
同时返回整除结果和余数 | divmod(10, 3) → (3, 1) |
pow() |
幂运算(等价于 **) |
pow(2, 3) → 8 |
round() |
四舍五入到指定小数位数 | round(3.1415, 2) → 3.14 |
max() |
求多个数值的最大值 | max(3, 7, 2) → 7 |
min() |
求多个数值的最小值 | min(3, 7, 2) → 2 |
len() |
返回字符串/列表等长度 | len("Hello") → 5 |
chr() |
将Unicode编码转为对应字符 | chr(97) → 'a' |
ord() |
将字符转为Unicode编码 | ord('a') → 97 |
数值函数逐个详解
| 函数 | 详细说明 |
|---|---|
| abs(x) | 计算x的绝对值。整数返回整数,浮点数返回浮点数。 如 abs(-10) → 10,abs(-3.5) → 3.5 |
| divmod(a, b) | 同时返回 (a // b, a % b),即商和余数组成的元组。 非常适合同时需要商和余数的时候一次计算完成。 如 divmod(10, 3) → (3, 1),divmod(7, 2) → (3, 1) |
| pow(a, b) | 计算 a 的 b 次方,等价于 a ** b。 如 pow(2, 3) → 8,pow(10, 2) → 100 |
| round(x, n) | 将x四舍五入保留n位小数。n省略时保留整数。 如 round(3.14159, 2) → 3.14,round(3.14159) → 3 |
| max(...) | 返回多个参数中的最大值。支持两个或更多参数。 如 max(10, 30, 20) → 30,max(-5, -10) → -5 |
| min(...) | 返回多个参数中的最小值。 如 min(10, 30, 20) → 10,min(-5, -10) → -10 |
input() 函数深度说明
input() 函数用于从键盘读取用户输入,默认返回的永远是字符串类型:
python
# input() 得到字符串
s = input("请输入:")
print(type(s)) # <class 'str'>
# 如果需要整数,必须用 int() 转换
num = int(input("请输入一个整数:"))
print(num + 100) # 可以正常运算
# 如果需要浮点数,用 float() 转换
price = float(input("请输入价格:"))
# 另一种方式:用 eval() 直接计算输入表达式
# eval() 会把输入当作Python表达式计算,得到表达式的结果
var = eval(input("请输入:"))
# 如果输入:123 → var 就是整数 123
# 如果输入:3.14 → var 就是浮点数 3.14
# 如果输入:"hello" → var 就是字符串
print() 函数的 end="" 参数
默认情况下,print() 每次输出后会自动换行。如果不希望换行,可以使用 end="" 参数:
python
# 默认用法:每次输出自动换行
print("Hello")
print("World")
# 输出:
# Hello
# World
# 使用 end="" 不换行
print("Hello", end="")
print("World")
# 输出:
# HelloWorld
# 可以指定其他结束符
print("A", end=", ")
print("B", end=", ")
print("C")
# 输出:
# A, B, C
字符编码转换:chr() 和 ord()
Python中每个字符对应一个 Unicode编码 整数。chr() 和 ord() 提供字符与编码的相互转换:
| 函数 | 功能 |
|---|---|
| ord(字符) | 将单个字符转换为它对应的Unicode编码(整数) |
| chr(编码) | 将Unicode编码(整数)转换为对应的字符 |
大小写字母的Unicode规律:
- 小写字母
'a'的编码是97,'b'是98...'z'是122 - 大写字母
'A'的编码是65,'B'是66...'Z'是90 - 大写字母编码 < 小写字母编码 :
ord('A') < ord('a')
使用示例:
python
# 字符转编码
print(ord('a')) # 输出:97
print(ord('A')) # 输出:65
print(ord('中')) # 输出:20013(中文也是Unicode)
# 编码转字符
print(chr(97)) # 输出:a
print(chr(65)) # 输出:A
print(chr(20013)) # 输出:中
# 大小写转换小技巧:大写加32得到小写
print(chr(ord('A') + 32)) # 输出:a
重要 :
input()返回的数据类型永远是字符串 ,如果需要数值计算,必须用int()或float()进行类型转换,也可以使用eval()。
2.6 math库
math库的三种导入方式
| 导入方式 | 语法 | 使用方式 | 优缺点 |
|---|---|---|---|
| 方式一:import 模块名 | import math |
math.pi, math.sqrt(16) |
需要加 math. 前缀,但不会污染命名空间,能明确知道函数来自哪个模块 |
| 方式二:from 模块名 import 具体函数 | from math import pi, sqrt |
直接用 pi, sqrt(16) |
不需要前缀,但只能使用导入的具体函数,其他函数仍需 math.xxx |
| 方式三:from 模块名 import * | from math import * |
直接用 pi, sqrt(16), ceil(3.2) 等 |
不需要前缀,方便快捷,但可能造成命名冲突,不推荐在大型项目中使用 |
三种方式示例对比:
python
# 方式一:import math(推荐)
import math
print(math.pi) # 输出 3.141592653589793
print(math.sqrt(16)) # 输出 4.0
print(math.ceil(3.2)) # 输出 4
# 方式二:from math import 具体函数
from math import pi, sqrt
print(pi) # 直接使用,不需要 math. 前缀
print(sqrt(16)) # 输出 4.0
# print(ceil(3.2)) # 错误!ceil 没有被导入
# 方式三:from math import *(不推荐)
from math import *
print(pi) # 直接使用
print(sqrt(16)) # 输出 4.0
print(ceil(3.2)) # 输出 4(所有函数都可以直接用)
考试注意 :
import math后必须用math.xxx调用函数,直接写sqrt(16)会报NameError。务必看清题目中的导入方式。
| 函数/常量 | 描述 | 示例 |
|---|---|---|
math.pi |
圆周率 π(约3.14159) | math.pi |
math.e |
自然常数 e(约2.71828) | math.e |
math.sqrt(x) |
求x的平方根 | math.sqrt(16) → 4.0 |
math.ceil(x) |
向上取整 | math.ceil(3.2) → 4 |
math.floor(x) |
向下取整 | math.floor(3.8) → 3 |
math.fabs(x) |
取绝对值(返回浮点数) | math.fabs(-5) → 5.0 |
math.pow(x, y) |
计算 x 的 y 次方 | math.pow(2, 3) → 8.0 |
math.sin(x) |
正弦(x为弧度) | math.sin(math.pi/2) → 1.0 |
math.cos(x) |
余弦(x为弧度) | math.cos(0) → 1.0 |
math.radians(x) |
角度转弧度 | math.radians(180) → 3.14159... |
使用示例
python
# 导入 math 库
import math
# 整型变量 r = 5
r = 5
# 圆周率 π
area = math.pi * r ** 2
# 打印输出到屏幕
print(f"半径为{r}的圆的面积是:{area:.2f}")
print(math.sqrt(16)) # 输出 4.0
print(math.ceil(4.2)) # 输出 5
print(math.floor(4.8)) # 输出 4
2.8 语句书写规范
良好的代码书写规范有助于提高代码可读性。
基本规范
python
# 整型变量 x = 10
x = 10
# 整型变量 y = 20
y = 20
total = price * quantity # 推荐
total=price*quantity # 不推荐
# 如果 x > 0
if x > 0:
print("x是正数") # 缩进4个空格
# 输入 → 存入变量 name
name = input("姓名:")
# 转为 整数 → 赋值给 age
age = int(input("年龄:"))
is_adult = age >= 18
# 打印输出到屏幕
print(f"{name}是{'成年人' if is_adult else '未成年人'}")
考试注意 :Python严格依赖缩进来识别代码块,错误的缩进会导致
IndentationError。
2.9 字符串格式化:str.format()
str.format() 是Python中一种强大且灵活的字符串格式化方法,常用于对输出内容进行精确的格式控制。
基本用法
python
# 基本占位符 {}
s = "我叫{},今年{}岁".format("张三", 18)
print(s) # 输出:我叫张三,今年18岁
# 按位置索引填充 {0}, {1}, {2}...
s = "{0}和{1}是好朋友".format("小明", "小红")
print(s) # 输出:小明和小红是好朋友
# 可以重复使用同一个索引
s = "{0}喜欢{1},{0}也喜欢{2}".format("小明", "篮球", "足球")
print(s) # 输出:小明喜欢篮球,小明也喜欢足球
填充、对齐与宽度
str.format() 最强大的功能是可以精确控制输出格式,语法为:
{:[填充字符][对齐方式][宽度]}
- 填充字符:用什么字符填充空白位置(默认为空格)
- 对齐方式 :
<左对齐、>右对齐、^居中对齐 - 宽度:总共占多少字符位置
python
# 左对齐,宽度10(默认空格填充)
print("{:<10}".format("Hello"))
# 输出: Hello (Hello后面跟5个空格)
# 右对齐,宽度10
print("{:>10}".format("Hello"))
# 输出: Hello(Hello前面有5个空格)
# 居中对齐,宽度10
print("{:^10}".format("Hello"))
# 输出: Hello (Hello前后各有空格)
# 用 * 号填充,左对齐,宽度20
print("{:*<20}".format("Python"))
# 输出: Python**************
# 用 * 号填充,右对齐,宽度20
print("{:*>20}".format("Python"))
# 输出: **************Python
# 用 * 号填充,居中对齐,宽度20
print("{:*^20}".format("Python"))
# 输出: *******Python*******
数字格式化(精度控制)
python
# 保留2位小数
print("{:.2f}".format(3.1415926))
# 输出: 3.14
# 宽度10,保留2位小数,右对齐
print("{:10.2f}".format(3.1415926))
# 输出: 3.14(前面有空格)
# 宽度20,用 * 填充,左对齐,保留3位小数
print("{:*<20.3f}".format(3.1415926))
# 输出: 3.142***************
# 宽度20,用 * 填充,右对齐,保留3位小数
print("{:*>20.3f}".format(3.1415926))
# 输出: ***************3.142
# 千分位分隔
print("{:,}".format(1234567890))
# 输出: 1,234,567,890
# 百分比格式
print("{:.2%}".format(0.8523))
# 输出: 85.23%
格式速查
| 格式说明符 | 含义 | 示例 |
|---|---|---|
{:.2f} |
保留2位小数 | 3.14159 → 3.14 |
{:10} |
宽度10,默认右对齐 | "Hi" → " Hi" |
{:<10} |
宽度10,左对齐 | "Hi" → "Hi " |
{:^10} |
宽度10,居中对齐 | "Hi" → " Hi " |
{:*<10} |
*填充,左对齐 |
"Hi" → "Hi********" |
{:>10.2f} |
宽度10,保留2位小数,右对齐 | 3.14 → " 3.14" |
{:,} |
千分位分隔 | 1000000 → "1,000,000" |
记忆口诀 :
:[填充字符][对齐方式][宽度][.精度][类型],按这个顺序理解即可。
例题
例题2-1(读程序写结果)
题目 :阅读以下温度转换程序,写出运行结果(假设用户输入 100)。
python
# 转为 浮点数 → 赋值给 c
c = float(input("请输入摄氏温度:"))
# 计算 → 赋值给 f
f = c * 9 / 5 + 32
# 打印输出到屏幕
print(f"华氏温度为:{f}")
答案/参考代码:
若输入 100,则运行结果为:
华氏温度为:212.0
解析 :摄氏100度转换为华氏的公式为 100 * 9 / 5 + 32 = 212.0。
例题2-2(读程序写结果)
题目:阅读以下变量交换程序,写出运行结果。
python
# 整型变量 a = 5
a = 5
# 整型变量 b = 10
b = 10
# 打印输出到屏幕
print(f"交换前:a={a}, b={b}")
temp = a
a = b
b = temp
# 打印输出到屏幕
print(f"交换后:a={a}, b={b}")
答案/参考代码:
交换前:a=5, b=10
交换后:a=10, b=5
解析 :通过临时变量 temp 实现两个变量值的交换:先将 a 的值保存到 temp,再将 b 的值赋给 a,最后将 temp 中保存的原 a 的值赋给 b。
例题2-3(补全程序题)
题目:以下程序从键盘输入两个整数,计算它们的**和、差、积、商(保留2位小数)**并输出。请补全空缺代码。
python
# 转为 整数 → 赋值给 a
a = int(input("请输入第一个整数:"))
# 转为 整数 → 赋值给 b
b = int(input("请输入第二个整数:"))
# 计算 → 赋值给 sum_result
sum_result = a + b
diff_result = ___________ # 计算差
prod_result = ___________ # 计算积
quot_result = ___________ # 计算商(保留2位小数)
# 打印输出到屏幕
print(f"和:{sum_result}")
# 打印输出到屏幕
print(f"差:{diff_result}")
# 打印输出到屏幕
print(f"积:{prod_result}")
# 打印输出到屏幕
print(f"商:{quot_result}")
答案/参考代码:
python
diff_result = a - b # 计算差
prod_result = a * b # 计算积
quot_result = round(a / b, 2) # 计算商(保留2位小数)
例题2-4(补全程序题)
题目:以下程序根据用户输入的姓名和年龄,输出格式化的自我介绍。请补全空缺代码。
python
# 输入 → 存入变量 name
name = input("请输入你的姓名:")
# 输入 → 存入变量 age
age = input("请输入你的年龄:")
# 字符串变量 intro,存储文本
intro = "大家好,我是" + _______ + ",今年" + _______ + "岁。"
# 打印输出到屏幕
print(intro)
first_char = _______ # 取出name的第一个字符
# 打印输出到屏幕
print(f"我姓「{first_char}」")
答案/参考代码:
python
# 字符串变量 intro,存储文本
intro = "大家好,我是" + name + ",今年" + age + "岁。"
# 打印输出到屏幕
print(intro)
first_char = name[0] # 取出name的第一个字符
# 打印输出到屏幕
print(f"我姓「{first_char}」")
例题2-5(编程题)
题目描述 :
编写程序,输入圆柱体的底面半径 r 和高 h(均为浮点数),使用 math 库计算并输出圆柱体的体积(体积公式:V = π * r² * h),结果保留2位小数。
参考代码:
python
# 导入 math 库
import math
# 转为 浮点数 → 赋值给 r
r = float(input("请输入圆柱体底面半径:"))
# 转为 浮点数 → 赋值给 h
h = float(input("请输入圆柱体的高:"))
# 圆周率 π
volume = math.pi * r ** 2 * h
# 打印输出到屏幕
print(f"圆柱体的体积为:{volume:.2f}")
例题2-6(编程题)
题目描述 :
编写程序,输入一个三位正整数(100-999),分别输出它的百位数字、十位数字和个位数字。
参考代码:
python
# 转为 整数 → 赋值给 num
num = int(input("请输入一个三位正整数:"))
hundreds = num // 100 # 百位
tens = (num // 10) % 10 # 十位
units = num % 10 # 个位
# 打印输出到屏幕
print(f"百位:{hundreds}")
# 打印输出到屏幕
print(f"十位:{tens}")
# 打印输出到屏幕
print(f"个位:{units}")
数位提取技巧:
- 百位:
num // 100- 十位:
(num // 10) % 10- 个位:
num % 10
2.10 考试提示
针对"读程序写结果"题型
- 算术运算优先级是必考内容,注意幂运算 > 乘除 > 加减
- 整除
//和取余%的区别要分清,特别是除数为负数时的情况 - 字符串拼接和重复运算的结果要能准确写出
- 逻辑运算短路规则常出现在读程序题中
针对"补全程序题"题型
- 类型转换 是常见考点:
input()返回字符串,计算前需用int()或float()转换 - 格式化输出
f-string的语法要熟练 - 注意
math库和random库函数的正确使用
针对"编程题"题型
- 熟练掌握数位提取(整除和取余结合)
- 掌握从键盘输入到输出的完整流程
- 注意
import语句的位置(通常放在程序开头) round()函数的使用以及 f-string 格式化输出的写法
课后练习
课后练习2-1(读程序写结果)
题目:阅读以下程序,写出运行结果。
python
# 导入 math 库
import math
# 整型变量 x = 16
x = 16
# 整型变量 y = 3
y = 3
# 平方根
result1 = math.sqrt(x)
# 计算 → 赋值给 result2
result2 = x // y
# 计算 → 赋值给 result3
result3 = x % y
result4 = (result1 > 4) and (result2 < 6)
# 打印输出到屏幕
print(f"result1={result1}")
# 打印输出到屏幕
print(f"result2={result2}")
# 打印输出到屏幕
print(f"result3={result3}")
# 打印输出到屏幕
print(f"result4={result4}")
答案:
result1=4.0
result2=5
result3=1
result4=False
解析:
math.sqrt(16)=4.016 // 3=5(整除取商)16 % 3=1(取余数)(4.0 > 4)为False,(5 < 6)为True,False and True=False
课后练习2-2(补全程序题)
题目 :以下程序使用 random 库生成两个 1~100 之间的随机整数,并输出它们的最大公约数(用辗转相除法,这里用 math.gcd)。请补全空缺代码。
python
# 导入 random 库
import random
# 导入 math 库
import math
# 随机整数 [a,b]
num1 = random.randint(1, 100)
num2 = _______________ # 生成另一个1~100的随机整数
gcd_result = _______________ # 使用math.gcd计算最大公约数
# 打印输出到屏幕
print(f"num1={num1}, num2={num2}")
# 打印输出到屏幕
print(f"最大公约数为:{gcd_result}")
答案:
python
num2 = random.randint(1, 100) # 生成另一个1~100的随机整数
gcd_result = math.gcd(num1, num2) # 使用math.gcd计算最大公约数
课后练习2-3(编程题)
题目描述 :
编写程序,输入一个浮点数表示商品的原价,再输入一个浮点数表示折扣率(如输入0.8表示打8折),计算并输出:
- 折后价格(保留2位小数)
- 节省了多少钱(保留2位小数)
参考代码:
python
# 转为 浮点数 → 赋值给 original_price
original_price = float(input("请输入商品原价:"))
# 转为 浮点数 → 赋值给 discount
discount = float(input("请输入折扣率(如0.8表示8折):"))
# 计算 → 赋值给 discounted_price
discounted_price = original_price * discount
# 计算 → 赋值给 saved_money
saved_money = original_price - discounted_price
# 打印输出到屏幕
print(f"折后价格:{discounted_price:.2f}元")
# 打印输出到屏幕
print(f"节省了:{saved_money:.2f}元")
本章模拟练习
模拟练习2-1(读程序写结果)
题目:阅读以下程序,写出运行结果。
python
# 整型变量 a = 15
a = 15
# 整型变量 b = 4
b = 4
# 打印输出到屏幕
print(a + b)
# 打印输出到屏幕
print(a - b)
# 打印输出到屏幕
print(a * b)
# 打印输出到屏幕
print(a / b)
# 打印输出到屏幕
print(a // b)
# 打印输出到屏幕
print(a % b)
# 打印输出到屏幕
print(a ** b)
答案:
19
11
60
3.75
3
3
50625
解析:
15 + 4 = 1915 - 4 = 1115 * 4 = 6015 / 4 = 3.75(普通除法,结果为浮点数)15 // 4 = 3(整除取商)15 % 4 = 3(取余数)15 ** 4 = 50625(15的4次方)
模拟练习2-2(补全程序题)
题目:以下程序输入一个三位正整数,计算各位数字的立方和。请补全空缺代码。
python
# 转为 整数 → 赋值给 num
num = int(input("请输入一个三位正整数:"))
a = _______________ # 百位数字
b = _______________ # 十位数字
c = _______________ # 个位数字
# 计算 → 赋值给 sum_cubes
sum_cubes = a**3 + b**3 + c**3
# 打印输出到屏幕
print(f"各位数字的立方和为:{sum_cubes}")
答案:
python
a = num // 100 # 百位数字
b = (num // 10) % 10 # 十位数字
c = num % 10 # 个位数字
模拟练习2-3(编程题)
题目描述 :
编写程序,模拟一个简单的猜数字游戏:
-
程序使用
random库生成一个 1~50 之间的随机整数作为目标数字 -
提示用户输入猜的数字(1~50)
-
计算猜的数字与目标数字的差值绝对值,并输出
-
输出格式示例:
目标数字已生成,请输入你的猜测(1~50):30
目标数字是:27
你猜的数字与目标数字相差:3
参考代码:
python
# 导入 random 库
import random
# 随机整数 [a,b]
target = random.randint(1, 50)
# 转为 整数 → 赋值给 guess
guess = int(input("目标数字已生成,请输入你的猜测(1~50):"))
# 计算 → 赋值给 diff
diff = abs(guess - target)
# 打印输出到屏幕
print(f"目标数字是:{target}")
# 打印输出到屏幕
print(f"你猜的数字与目标数字相差:{diff}")
第3章 基本控制结构
3.1 三种控制结构
程序有三种基本的控制结构:
+---------------+ +---------------+ +---------------+
| 顺序结构 | | 选择结构 | | 循环结构 |
| (Sequential) | | (Selection) | | (Iteration) |
+---------------+ +---------------+ +---------------+
| 从上到下依次 | | 根据条件决定 | | 重复执行某段 |
| 执行所有语句 | | 执行哪段代码 | | 代码(直到条件 |
| | | | | 不满足为止) |
+---------------+ +---------------+ +---------------+
3.2 顺序结构
顺序结构是最简单的控制结构,程序从上到下逐行执行。
python
# 打印输出到屏幕
print("第一步:开始")
# 整型变量 x = 10
x = 10
# 整型变量 y = 20
y = 20
# 计算 → 赋值给 z
z = x + y
# 打印输出到屏幕
print(f"第二步:计算结果为{z}")
# 打印输出到屏幕
print("第三步:结束")
3.3 分支结构(选择结构)
3.3.1 单分支:if
python
# 如果 条件
if 条件:
条件为True时执行的代码块
python
# 整型变量 score = 85
score = 85
# 如果 score >= 60
if score >= 60:
# 打印输出到屏幕
print("恭喜,考试及格!")
3.3.2 双分支:if-else
python
# 如果 条件
if 条件:
条件为True时执行的代码块
# 否则
else:
条件为False时执行的代码块
python
# 整型变量 age = 17
age = 17
# 如果 age >= 18
if age >= 18:
# 打印输出到屏幕
print("已成年")
# 否则
else:
# 打印输出到屏幕
print("未成年")
3.3.3 多分支:if-elif-else
python
# 如果 条件1
if 条件1:
条件1为True时执行
# 否则如果 条件2
elif 条件2:
条件2为True时执行(条件1为False)
# 否则如果 条件3
elif 条件3:
条件3为True时执行(条件1、2为False)
# 否则
else:
所有条件均为False时执行
python
# 整型变量 score = 85
score = 85
# 如果 score >= 90
if score >= 90:
# 打印输出到屏幕
print("优秀")
# 否则如果 score >= 80
elif score >= 80:
# 打印输出到屏幕
print("良好")
# 否则如果 score >= 70
elif score >= 70:
# 打印输出到屏幕
print("中等")
# 否则如果 score >= 60
elif score >= 60:
# 打印输出到屏幕
print("及格")
# 否则
else:
# 打印输出到屏幕
print("不及格")
注意 :
if-elif-else结构中,条件按顺序判断,一旦有一个条件满足,就执行对应的代码块,然后跳出整个结构,不会再判断后续条件。
3.3.4 嵌套分支
python
# 整型变量 score = 85
score = 85
# 如果 score >= 60
if score >= 60:
# 如果 score >= 90
if score >= 90:
# 打印输出到屏幕
print("优秀")
# 否则
else:
# 打印输出到屏幕
print("及格")
# 否则
else:
# 打印输出到屏幕
print("不及格")
3.4 循环结构
3.4.1 for 循环
for 循环用于遍历一个可迭代对象(如 range()、字符串、列表等)。
基本语法:
python
# 遍历 可迭代对象
for 变量 in 可迭代对象:
循环体
结合 range() 使用:
python
for i in range(5): # 输出0,1,2,3,4
# 打印输出到屏幕
print(i, end=" ")
print() # 换行
for i in range(2, 6): # 输出2,3,4,5
# 打印输出到屏幕
print(i, end=" ")
# 打印输出到屏幕
print()
for i in range(1, 10, 2): # 输出1,3,5,7,9
# 打印输出到屏幕
print(i, end=" ")
注意 :
range(stop)包含起始值,不包含结束值 ,即取值范围是[start, stop)。
3.4.2 while 循环
while 循环在条件为 True 时反复执行循环体。
python
# 当 条件 时循环
while 条件:
循环体
python
# 整型变量 i = 1
i = 1
# 整型变量 total = 0
total = 0
# 当 i <= 100 时循环
while i <= 100:
# total += 运算
total += i
# i += 运算
i += 1
print(f"1到100的和为:{total}") # 输出5050
危险 :如果条件始终为
True,循环将无限进行下去(死循环 )。一定要确保循环条件最终会变为False。
3.4.3 循环嵌套
循环内部再包含循环,称为循环嵌套。外层循环每执行一次,内层循环完整执行一轮。
python
# 遍历 range(1, 10)
for i in range(1, 10):
# 遍历 range(1, i + 1)
for j in range(1, i + 1):
# 打印输出到屏幕
print(f"{j}×{i}={i*j}", end="\t")
print() # 换行
3.4.4 break 和 continue
| 语句 | 作用 | 示例 |
|---|---|---|
break |
立即结束当前循环,跳出循环体 | 找到目标后提前终止搜索 |
continue |
跳过本轮循环剩余语句,进入下一轮 | 跳过不符合条件的元素 |
python
# 遍历 range(1, 50)
for i in range(1, 50):
# 如果 i % 7 == 0
if i % 7 == 0:
# 打印输出到屏幕
print(f"找到第一个能被7整除的数:{i}")
break # 找到后立即退出循环
# 遍历 range(1, 11)
for i in range(1, 11):
if i % 2 != 0: # 如果是奇数
continue # 跳过本轮,不输出
# 打印输出到屏幕
print(i, end=" ")
3.4.5 for 与 else 搭配
在 Python 中,for 循环可以和 else 搭配使用,这是 Python 的一个特有语法,其他语言里比较少见。
语法:
python
for 变量 in 序列:
循环体
if 条件:
break # 提前退出
else:
# 循环正常结束时执行(没有碰到 break)
语句块
关键规则:
| 循环结束方式 | else 是否执行 |
|---|---|
正常遍历完毕(没有触发 break) |
执行 else 代码块 |
break 提前退出循环 |
不执行 else 代码块 |
示例1:找到偶数后 break(不执行 else)
python
# 遍历 range(2, 10)
for i in range(2, 10):
# 如果 i % 2 == 0
if i % 2 == 0:
# 打印输出到屏幕
print(f"{i}是偶数,停止查找")
# 终止循环
break
# 否则
else:
print("没有找到偶数") # 不会执行,因为2就是偶数,触发了break
输出 :2是偶数,停止查找(else 不执行)
示例2:素数判断(for...else 经典应用)
判断一个数是否为素数(质数)。素数是指大于1,且只能被1和自身整除的自然数。
python
# 转为 整数 → 赋值给 num
num = int(input("请输入一个正整数:"))
# 如果 num > 1
if num > 1:
# 遍历 range(2, int(num ** 0.5) + 1)
for i in range(2, int(num ** 0.5) + 1):
# 如果 num % i == 0(找到因子,不是素数)
if num % i == 0:
# 打印输出到屏幕
print(f"{num} 不是素数,因为能被 {i} 整除")
# 终止循环(提前退出,不执行 else)
break
# 循环正常结束(没找到任何因子),执行 else
else:
# 打印输出到屏幕
print(f"{num} 是素数")
# 否则(num <= 1)
else:
# 打印输出到屏幕
print(f"{num} 不是素数(素数必须大于 1)")
测试运行:
# 输入 17
请输入一个正整数:17
17 是素数
# 输入 15
请输入一个正整数:15
15 不是素数,因为能被 3 整除
# 输入 2
请输入一个正整数:2
2 是素数
for...else 的执行逻辑图解:
遍历 range(2, sqrt(num)+1)
找到因子?──是──> break ──> else 不执行
│
否(继续遍历)
↓
遍历完毕(没找到任何因子)
↓
执行 else ──> 确认是素数
记忆技巧 :可以把
for...else理解为"找茬 "模式------如果循环里没有"毛病"(没触发break),就执行else。素数判断正是这种模式:遍历所有可能的因子,如果找到一个能整除的就break(有问题);如果全找完都没break(没毛病),说明是素数。
3.5 异常处理
使用 try-except 来处理程序运行时可能出现的错误,避免程序崩溃。
python
# 尝试(捕捉异常)
try:
# 转为 整数 → 赋值给 num
num = int(input("请输入一个整数:"))
# 计算 → 赋值给 result
result = 10 / num
# 打印输出到屏幕
print(f"10 ÷ {num} = {result}")
# 捕获 ValueError
except ValueError:
# 打印输出到屏幕
print("输入错误:请输入有效的整数!")
# 捕获 ZeroDivisionError
except ZeroDivisionError:
# 打印输出到屏幕
print("数学错误:除数不能为0!")
except Exception as e:
# 打印输出到屏幕
print(f"发生未知错误:{e}")
# 否则
else:
# 打印输出到屏幕
print("计算成功完成!")
finally:
# 打印输出到屏幕
print("程序执行结束。")
例题
例题3-1(读程序写结果)
题目:阅读以下程序,写出运行结果。
python
# 整型变量 score = 75
score = 75
# 如果 score >= 90
if score >= 90:
# 字符串变量 grade,存储文本
grade = "A"
# 否则如果 score >= 80
elif score >= 80:
# 字符串变量 grade,存储文本
grade = "B"
# 否则如果 score >= 70
elif score >= 70:
# 字符串变量 grade,存储文本
grade = "C"
# 否则如果 score >= 60
elif score >= 60:
# 字符串变量 grade,存储文本
grade = "D"
# 否则
else:
# 字符串变量 grade,存储文本
grade = "E"
# 打印输出到屏幕
print(f"成绩等级为:{grade}")
答案/参考代码:
成绩等级为:C
解析 :score = 75,依次判断:
score >= 90为False,跳过score >= 80为False,跳过score >= 70为True,执行grade = "C",然后跳出整个 if-elif 结构
例题3-2(补全程序题)
题目 :以下程序使用 while 循环计算 1 到 n 之间所有整数的累加和。请补全空缺代码。
python
# 转为 整数 → 赋值给 n
n = int(input("请输入一个正整数 n:"))
# 整型变量 i = 1
i = 1
# 整型变量 total = 0
total = 0
while _______ : # 循环条件
# total += 运算
total += i
_______ # 更新循环变量
# 打印输出到屏幕
print(f"1到{n}的和为:{total}")
测试:当 n = 100 时,结果应为 5050。
答案/参考代码:
python
while i <= n: # 循环条件
i += 1 # 更新循环变量
解析 :while 循环从 i = 1 开始,每次累加 i 到 total,然后 i 自增1,直到 i > n 时结束循环。
例题3-3(读程序写结果)
题目:阅读以下程序,写出运行结果。
python
# 遍历 range(1, 8)
for i in range(1, 8):
# 如果 i % 3 == 0
if i % 3 == 0:
# 跳过本轮
continue
# 打印输出到屏幕
print(i, end=" ")
答案/参考代码:
1 2 4 5 7
解析 :range(1, 8) 生成数字 1,2,3,4,5,6,7。
- 当
i能被3整除时(即3和6),continue跳过print语句 - 因此输出的是不能被3整除的数:1, 2, 4, 5, 7
例题3-4(编程题)
题目描述 :
编写程序,输出一个由星号 * 组成的等腰直角三角形,行数由用户输入。
例如,输入 5,输出如下:
*
**
***
****
*****
参考代码:
python
# 转为 整数 → 赋值给 n
n = int(input("请输入行数:"))
# 遍历 range(1, n + 1)
for i in range(1, n + 1):
# 遍历 range(i)
for j in range(i):
# 打印输出到屏幕
print("*", end="")
print() # 换行
解析 :外层循环控制行数(第 i 行),内层循环控制每行打印 i 个星号。
例题3-5(补全程序题)
题目 :以下程序实现:用户输入两个整数,计算它们的商(结果保留2位小数)。要求使用 try-except 处理可能出现的异常(分母为0或输入非数字)。请补全空缺代码。
python
_______ : # 异常处理开始
# 转为 浮点数 → 赋值给 a
a = float(input("请输入被除数:"))
# 转为 浮点数 → 赋值给 b
b = float(input("请输入除数:"))
# 计算 → 赋值给 result
result = a / b
# 打印输出到屏幕
print(f"结果为:{result:.2f}")
_______ ValueError: # 处理输入非数字的情况
# 打印输出到屏幕
print("错误:请输入有效的数字!")
_______ ZeroDivisionError: # 处理除数为0的情况
# 打印输出到屏幕
print("错误:除数不能为0!")
答案/参考代码:
python
try: # 异常处理开始
# 转为 浮点数 → 赋值给 a
a = float(input("请输入被除数:"))
# 转为 浮点数 → 赋值给 b
b = float(input("请输入除数:"))
# 计算 → 赋值给 result
result = a / b
# 打印输出到屏幕
print(f"结果为:{result:.2f}")
except ValueError: # 处理输入非数字的情况
# 打印输出到屏幕
print("错误:请输入有效的数字!")
except ZeroDivisionError: # 处理除数为0的情况
# 打印输出到屏幕
print("错误:除数不能为0!")
3.6 考试提示
针对"读程序写结果"题型
- if-elif-else 多分支:重点判断条件是互斥的,只有一个分支会执行
- 循环 + break/continue:准确理解 break(终止整个循环)和 continue(跳过本轮)的区别
- 循环嵌套:注意外层循环每执行一次,内层循环完整执行一轮
针对"补全程序题"题型
- 循环三要素:初始条件、循环条件、循环变量更新,缺一不可
- 注意
range()的起始值和结束值(包含起始,不包含结束) try-except的语法结构要熟练掌握
针对"编程题"题型
- 循环嵌套常用于打印图形(三角形、菱形、乘法表等)
- 累加求和 :
total = 0; for i in range(...): total += i - 异常处理:对可能的用户输入错误进行防护
课后练习
课后练习3-1(读程序写结果)
题目:阅读以下程序,写出运行结果。
python
# 整型变量 total = 0
total = 0
# 遍历 range(1, 6)
for i in range(1, 6):
# 如果 i % 2 == 0
if i % 2 == 0:
# 跳过本轮
continue
# total += 运算
total += i
# 打印输出到屏幕
print(total)
答案:
9
解析 :range(1, 6) 生成 1,2,3,4,5。
- 当
i为偶数(2和4)时,continue跳过total += i - 只累加奇数:1 + 3 + 5 = 9
课后练习3-2(补全程序题)
题目:以下程序输入一个正整数 n,输出 n 的所有正因数。请补全空缺代码。
python
# 转为 整数 → 赋值给 n
n = int(input("请输入一个正整数:"))
# 打印输出到屏幕
print(f"{n}的所有正因数为:", end="")
for i in range(1, _______): # 循环范围
if _______ : # 判断i是否是n的因数
# 打印输出到屏幕
print(i, end=" ")
测试:输入 12,输出应为 1 2 3 4 6 12。
答案:
python
for i in range(1, n + 1): # 循环范围:1到n
if n % i == 0: # 判断i是否是n的因数
# 打印输出到屏幕
print(i, end=" ")
课后练习3-3(编程题)
题目描述 :
编写一个猜数字游戏,规则如下:
- 程序生成一个 1~100 之间的随机整数
- 用户有最多 5 次机会猜这个数字
- 每次猜测后,程序提示"猜大了"或"猜小了"
- 如果猜对了,输出"恭喜你猜对了!共猜了X次"
- 如果5次都没猜对,输出"很遗憾,正确答案是:XX"
参考代码:
python
# 导入 random 库
import random
# 随机整数 [a,b]
target = random.randint(1, 100)
# 整型变量 max_attempts = 5
max_attempts = 5
# 打印输出到屏幕
print("猜数字游戏(1~100),你有5次机会!")
# 遍历 range(1, max_attempts + 1)
for attempt in range(1, max_attempts + 1):
# 转为 整数 → 赋值给 guess
guess = int(input(f"第{attempt}次猜测,请输入数字:"))
# 如果 guess == target
if guess == target:
# 打印输出到屏幕
print(f"恭喜你猜对了!共猜了{attempt}次")
# 终止循环
break
# 否则如果 guess > target
elif guess > target:
# 打印输出到屏幕
print("猜大了")
# 否则
else:
# 打印输出到屏幕
print("猜小了")
# 否则
else:
# 打印输出到屏幕
print(f"很遗憾,正确答案是:{target}")
本章模拟练习
模拟练习3-1(读程序写结果)
题目:阅读以下程序,写出运行结果。
python
# 遍历 range(1, 4)
for i in range(1, 4):
# 遍历 range(1, i + 1)
for j in range(1, i + 1):
# 打印输出到屏幕
print(j, end="")
# 打印输出到屏幕
print()
答案:
1
12
123
解析:
- i=1时,内层循环 j 从1到1,输出 "1",换行
- i=2时,内层循环 j 从1到2,输出 "12",换行
- i=3时,内层循环 j 从1到3,输出 "123",换行
模拟练习3-2(补全程序题)
题目:以下程序输入一个正整数 n,判断它是否为素数(只能被1和自身整除的数)。请补全空缺代码。
python
# 导入 math 库
import math
# 转为 整数 → 赋值给 n
n = int(input("请输入一个正整数:"))
# 如果 n <= 1
if n <= 1:
# 打印输出到屏幕
print(f"{n}不是素数")
# 否则
else:
# 布尔变量 is_prime = True(真)
is_prime = True
# 平方根
for i in range(2, int(math.sqrt(n)) + 1):
if _______ : # 如果能被i整除
# 布尔变量 is_prime = False(假)
is_prime = False
_______ # 找到因数后退出循环
# 如果 is_prime
if is_prime:
# 打印输出到屏幕
print(f"{n}是素数")
# 否则
else:
# 打印输出到屏幕
print(f"{n}不是素数")
答案:
python
if n % i == 0: # 如果能被i整除
break # 找到因数后退出循环
模拟练习3-3(编程题)
题目描述 :
编写程序,输入一个正整数 n,计算并输出以下数列前 n 项的和:
S = 1 + 1/2 + 1/3 + 1/4 + ... + 1/n
结果保留3位小数。
参考代码:
python
# 转为 整数 → 赋值给 n
n = int(input("请输入正整数 n:"))
# 浮点变量 total = 0.0(带小数)
total = 0.0
# 遍历 range(1, n + 1)
for i in range(1, n + 1):
# total += 运算
total += 1 / i
# 打印输出到屏幕
print(f"前{n}项的和为:{total:.3f}")
3.5 random库的使用
Python内置了random模块,用于生成随机数。常用函数如下:
| 函数 | 功能 |
|---|---|
random.random() |
生成 [0, 1) 之间的随机浮点数 |
random.randint(a, b) |
生成 a, b 之间的随机整数(包含两端) |
random.randrange(start, stop, step) |
类似range返回步长序列中随机一个数 |
random.choice(seq) |
从序列中随机选择一个元素 |
random.sample(seq, k) |
从序列中随机选择k个元素(不重复) |
random.uniform(a, b) |
生成 a, b 之间的随机浮点数 |
random.shuffle(lst) |
原地打乱列表(改变原列表) |
random.seed(n) |
设置随机种子,使结果可复现 |
示例:
python
import random
# 1~10之间的随机整数
print(random.randint(1, 10))
# 从列表随机选一个
colors = ['红', '绿', '蓝']
print(random.choice(colors))
# 从1-50随机选5个
print(random.sample(range(1, 51), 5))
# 打乱列表
cards = list(range(1, 13))
random.shuffle(cards)
print(cards)
# 设置随机种子复现结果
random.seed(42)
print(random.randint(1, 100)) # 固定输出:82
random.seed(42)
print(random.randint(1, 100)) # 再次固定输出:82
3.6 循环的 else 子句
Python中,for和while循环都可以带else子句,当循环正常结束(未遇到break)时执行else ;若被break提前退出,则不执行else。
语法:
python
for 变量 in 序列:
循环体
if 条件:
break
else:
# 循环正常走完没break时执行
素数判断示例:
python
n = int(input("请输入一个整数:"))
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
print(f"{n} 不是素数")
break
else:
# 没有找到任何因子
print(f"{n} 是素数")