Python编程:从入门到实践

这是基于 《Python编程:从入门到实践》这本书以一个初学者的视角去学习而记录的笔记,浓缩了精华的部分以及分享了一些我自己的见解。做这个既是为了让自己边学边记录也是为了保留自己的问题去和小伙伴一起谈论。

 一,python是什么以及核心作用

Python 是一种高级、解释型、面向对象的编程语言,由荷兰人 Guido van Rossum 于 1989 年圣诞节期间创建,第一个公开发行版发行于 1991 年。它的设计哲学强调代码的可读性和简洁的语法,特别是使用空格缩进划分代码块,而非使用大括号或关键词。

核心特点:

  1. 可读性强:代码简洁易读,被称为 “可执行的伪代码”。
  2. 解释型语言:无需编译,可直接运行,开发效率高。
  3. 动态类型:变量类型无需预先声明,灵活高效。
  4. 面向对象:支持面向对象编程的所有特性。
  5. 跨平台:可在 Windows、Linux、macOS 等多种系统运行。
  6. 丰富的标准库和第三方库:涵盖 Web 开发、数据科学、人工智能等几乎所有领域。

核心作用:

  1. Web 开发:通过 Django、Flask 等框架快速构建网站和 API。
  2. 数据科学与机器学习:NumPy、Pandas 用于数据分析,Scikit-learn、TensorFlow 用于模型训练。
  3. 自动化脚本:系统管理、文件处理、批量任务等自动化操作。
  4. 游戏开发:Pygame 库可创建 2D 游戏。
  5. 网络爬虫:Requests、BeautifulSoup、Scrapy 用于数据采集。
  6. 桌面应用开发:Tkinter、PyQt 等构建 GUI 程序。
  7. DevOps:Ansible、SaltStack 等工具基于 Python 开发。

第2章变量和简单数据类型

2.1字面量

2.1.1 什么是字面量

在代码中,被写下来的固定的值(数据),叫做字面量

2.2 什么是变量

简单的说,变量就是在程序运行时,记录数据用的

在程序中可随时修改变量的值,而Python将始终记录变量的最新值。

message = "Hello Python world!"
print(message)
message = "Hello Python Crash Course world!"
print(message)

输出为:
Hello Python world!
Hello Python Crash Course world!

2.2.1 变量的命名和使用

1.变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头

2.变量名不能包含空格

3.就目前而言,应使用小写的Python变量名。在变量名中使用大写字母虽然不会导致错误,但避免使用大写字母是个不错的主意

2.3 字符串

1.字符串就是一系列字符。在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号

2.3.1 使用方法修改字符串的大小写

name = "ada lovelace"
print(name.upper()) //头部大写
print(name.lower())  //所以的大写
print(name.title())  //全小写

结果:
Ada Lovelace
ADA LOVELACE
ada lovelace

 2.3.2 合并(拼接)字符串

Python使用加号(+)来合并字符串

first_name = "ada"
last_name = "lovelace"
full_name = first_name+" "+last_name
print("Hello,"+full_name.title()+"!") 


结果:
Hello,Ada Lovelace!

2.3.3 使用制表符或换行符来添加空白 

"\n\t"让Python换到下一行,并在下一行开头添加一个制表符

>>>print("Languages:\n\tPython\n\tC\n\tJavaScript")
Languages:
    Python
    C
    JavaScript

2.3.4 删除空白 

可以剔除字符串开头的空白,结尾的空白,或同时剔除字符串两端的空白。为此,可分别使用方法lstrip(),rstrip(和strip()

>>>favorite_language = 'python ' ❶
>>>favorite_language.rstrip() ❷
'python'  //结尾的
>>>favorite_language.lstrip() ❸
'python '  //开头的
>>>favorite_language.strip() ❹
'python'  //两头的

2.3.5 练习:

1.将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello Eric,would you like to learnsome Python today?”​。

user_name = "eric"
print("Hello,"+user_name.title()+",would you like to learn some Python today?")

 2.剔除人名中的空白:存储一个人名,并在其开头和末尾都包含一些空白字符。务必至少使用字符组合"\t"和"\n"各一次。

user_name = " eric "
print("Hello,"+user_name.strip()+"\n\tnice to meet you")

结果:
Hello,eric
	nice to meet you

2.4 数字

2.4.1 整数

可对整数执行加(+)减(-)乘(*)除(/)运算。

>>>2+3
5
>>>3 - 2
1
>>>2 * 3
6
>>>3 / 2
1.5

2.4.2 浮点数

Python将带小数点的数字都称为浮点数

2.4.3 使用函数str()避免类型错误

age = 23
message = "Happy "+age+"rd Birthday!"
print(message)


//Python发现你使用了一个值为整数(int)的变量,
但它不知道该如何解读这个值
Traceback (most recent call last):
  File "birthday.py",line 2,in <module>
    message = "Happy "+age+"rd Birthday!"
TypeError:Can't convert 'int'object to str implicitly ❶

可调用函数str(),它让Python将非字符串值表示为字符串:

age = 23
message = "Happy "+str(age)+"rd Birthday!"
print(message)

Happy 23rd Birthday!

2.5 注释 

1.注释:在程序代码中对程序代码进行解释说明的文字。 作用:注释不是程序,不能被执行

单行注释:通过 # 号定义,在#号右侧的所有内容均作为注释

2.用快捷键ctrl+/就可以选中要注释的部分,可以单行也可以多行注释

2.6小结

在本章中,你学习了:如何使用变量;如何创建描述性变量名以及如何消除名称错误和语法错误;字符串是什么,以及如何使用小写、大写和首字母大写方式显示字符串;使用空白来显示整洁的输出,以及如何剔除字符串中多余的空白;如何使用整数和浮点数;使用数值数据时需要注意的意外行为。你还学习了如何编写说明性注释,让代码对你和其他人来说更容易理解。最后,你了解了让代码尽可能简单的理念。

第3章列表简介

你将学习列表是什么以及如何使用列表元素。列表让你能够在一个地方存储成组的信息,其中可以只包含几个元素,也可以包含数百万个元素。

 3.1 列表是什么

列表由一系列按特定顺序排列的元素组成。你可以创建包含字母表中所有字母、数字0~9或所有家庭成员姓名的列表;也可以将任何东西加入列表中,其中的元素之间可以没有任何关系。

在Python中,用方括号([​])来表示列表,并用逗号来分隔其中的元素。

bicycles = ['trek','cannondale','redline','specialized']
print(bicycles)


['trek','cannondale','redline','specialized']

3.1.1 访问列表元素 

要访问列表元素,可指出列表的名称,再指出元素的索引,并将其放在方括号内。

bicycles = ['trek','cannondale','redline','specialized']
print(bicycles[1])
print(bicycles[3])
print(bicycles[-1]) //倒数第一个


cannondale
specialized
specialized 

3.2 修改、添加和删除元素

3.2.1 修改列表元素

例如,假设有一个摩托车列表,其中的第一个元素为'honda',如何修改它的值呢?

motorcycles = ['honda','yamaha','suzuki'] ❶
print(motorcycles)
motorcycles[0] = 'ducati'❷
print(motorcycles)

输出表明,第一个元素的值确实变了,但其他列表元素的值没变:
['honda','yamaha','suzuki']
['ducati','yamaha','suzuki']

3.2.2 在列表中添加元素 

1.在列表末尾添加元素

方法append()将元素'ducati'添加到了列表末尾

例如,你可以先创建一个空列表,再使用一系列的append()语句添加元素。
下面来创建一个空列表,再在其中添加元素'honda'、'yamaha'和'suzuki':

motorcycles = []
motorcycles.append('honda')
motorcycles.append('yamaha')
motorcycles.append('suzuki')
print(motorcycles)

结果:
['honda','yamaha','suzuki']
2.在列表中插入元素 

使用方法insert()可在列表的任何位置添加新元素。为此,你需要指定新元素的索引和值

motorcycles = ['honda','yamaha','suzuki']
motorcycles.insert(2,'ducati') 
print(motorcycles)

结果:
['honda', 'yamaha', 'ducati', 'suzuki']

3.2.3 从列表中删除元素 

1.使用del语句删除元素

motorcycles = ['honda','yamaha','suzuki']
print(motorcycles)
del motorcycles[1]
print(motorcycles)

结果:
['honda','yamaha','suzuki']
['honda','suzuki']

2.使用方法pop()删除元素

方法pop()可删除列表末尾的元素,并让你能够接着使用它。术语弹出(pop)源自这样的类比:列表就像一个栈,而删除列表末尾的元素相当于弹出栈顶元素。

motorcycles = ['honda','yamaha','suzuki'] ❶
print(motorcycles)
popped_motorcycle = motorcycles.pop(1) ❷
print(motorcycles) ❸
print(popped_motorcycle) ❹


['honda','yamaha','suzuki']
['honda','yamaha']
yamaha

最后,我们打印弹出的值,以证明我们依然能够访问被删除的值(见❹)

如果你不确定该使用del语句还是pop()方法,下面是一个简单的判断标准:如果你要从列表中删除一个元素,且不再以任何方式使用它,就使用del语句;如果你要在删除元素后还能继续使用它,就使用方法pop()。

3.根据值删除元素

如果你只知道要删除的元素的值,可使用方法remove(),使用remove()从列表中删除元素时,也可接着使用它的值。

motorcycles = ['honda','yamaha','suzuki','ducati'] ❶
print(motorcycles)
too_expensive = 'ducati'❷
motorcycles.remove(too_expensive) ❸
print(motorcycles)
print("\nA "+too_expensive.title()+" is too expensive for me.") ❹

['honda','yamaha','suzuki','ducati']
['honda','yamaha','suzuki']
A Ducati is too expensive for me.

3.3 组织列表 

3.3.1 使用方法sort()对列表进行永久性排序

方法sort()(见❶)永久性地修改了列表元素的排列顺序 。sort(顺序)

cars = ['bmw','audi','toyota','subaru']
cars.sort() ❶
print(cars)

['audi','bmw','subaru','toyota']

你还可以按与字母顺序相反的顺序排列列表元素,为此,只需向sort()方法传递参数reverse=True。 reverse(逆转,相反)

cars = ['bmw','audi','toyota','subaru']
cars.sort(reverse=True)
print(cars)

['toyota','subaru','bmw','audi']

3.3.2 使用函数sorted()对列表进行临时排序 

可使用函数sorted()。函数sorted()让你能够按特定顺序显示列表元素,同时不影响它们在列表中的原始排列顺序.

cars = ['bmw','audi','toyota','subaru']
print("Here is the original list:") ❶
print(cars)
print("\nHere is the sorted list:") ❷
print(sorted(cars))
print("\nHere is the original list again:") ❸
print(cars)

结果:
Here is the original list:
['bmw','audi','toyota','subaru']
Here is the sorted list:
['audi','bmw','subaru','toyota']
Here is the original list again:❹
['bmw','audi','toyota','subaru']

3.3.3 倒着打印列表 

方法reverse()永久性地修改列表元素的排列顺序,但可随时恢复到原来的排列顺序,为此只需对列表再次调用reverse()即可。

cars = ['bmw','audi','toyota','subaru']
print(cars)
cars.reverse()
print(cars)

['bmw','audi','toyota','subaru']
['subaru','toyota','audi','bmw']

3.3.4 确定列表的长度 

使用函数len()可快速获悉列表的长度。

>>>cars = ['bmw','audi','toyota','subaru']
>>>len(cars)
4

3.3.5 练习

1.放眼世界:

想出至少5个你渴望去旅游的地方。·将这些地方存储在一个列表中,并确保其中的元素不是按字母顺序排列的。·按原始排列顺序打印该列表。不要考虑输出是否整洁的问题,只管打印原始Python列表。

·使用sorted()按字母顺序打印这个列表,同时不要修改它。·再次打印该列表,核实排列顺序未变。·使用sorted()按与字母顺序相反的顺序打印这个列表,同时不要修改它。·再次打印该列表,核实排列顺序未变。

·使用reverse()修改列表元素的排列顺序。打印该列表,核实排列顺序确实变了。

·使用reverse()再次修改列表元素的排列顺序。打印该列表,核实已恢复到原来的排列顺序。

·使用sort()修改该列表,使其元素按字母顺序排列。打印该列表,核实排列顺序确实变了。

place = ['nanchang','sh','bj','sz','yichun']

print(sorted(place))#按字母顺序打印,不永久

print(sorted(place,reverse=True))#倒着打印
print(place)

place.reverse()#到着打印,永久性
print(place)

place.reverse()#回到原来的顺序
print(place)

place.sort()#永久按字母顺序排序
print(place)

第4章操作列表

在本章中,你将学习如何遍历整个列表,这只需要几行代码,无论列表有多长。循环让你能够对列表的每个元素都采取一个或一系列相同的措施,从而高效地处理任何长度的列表,包括包含数千乃至数百万个元素的列表。

4.1 遍历整个列表 

需要对列表中的每个元素都执行相同的操作时,可使用Python中的for循环。

4.1.1 深入地研究循环

语法:
for 临时变量 in 目标对象:
    循环体
    
1.
total = 0
for num in range(1,6):            
total+=num       
print("累加和为:",total)

累加和为: 1
累加和为: 3
累加和为: 6
累加和为: 10
累加和为: 15


2.
max_attempts = 3

for attempt in range(max_attempts):
    password = input("请输入正确密码(还剩 %d 次尝试): " % (max_attempts - attempt))
    if password == "12345":
        print("密码正确,欢迎登录!")
        break  # 正确输入后终止循环
else:  # 循环正常结束(未触发 break)
    print("尝试次数过多,登录失败!")

    
请输入正确密码(还剩 3 次尝试): 12
请输入正确密码(还剩 2 次尝试): 21
请输入正确密码(还剩 1 次尝试): 12
尝试次数过多,登录失败!

进程已结束,退出代码为 0

4.1.2 在for循环结束后执行一些操作

在for循环后面,没有缩进的代码都只执行一次,而不会重复执行

magicians = ['alice','david','carolina']
for magician in magicians:
    print(magician.title()+",that was a great trick!")
    print("I can't wait to see your next trick,"+magician.title()+".\n")
print("Thank you,everyone.That was a great magic show!") ❶


Alice,that was a great trick!
I can't wait to see your next trick,Alice.
David,that was a great trick!
I can't wait to see your next trick,David.
Carolina,that was a great trick!
I can't wait to see your next trick,Carolina.
Thank you,everyone.That was a great magic show!
你在前面看到了,开头两条print语句针对列表中每位魔术师重复执行。然而,由于第三条print语句没有缩进,因此只执行一次:因为缩进了就会被看成if的循环体,而没有缩进就不会被循环。在写代码的过程中要避免不必要的缩进。 

 4.2.1 遗漏了冒号

for语句末尾的冒号告诉Python,下一行是循环的第一行。如果遗漏了也会导致错误

4.3 创建数值列表

列表非常适合用于存储数字集合,而Python提供了很多工具,可帮助你高效地处理数字列表。

4.3.1 使用函数range()

Python函数range()让你能够轻松地生成一系列的数字
for value in range(1,5):
    print(value)

结果:
1
2
3
4

在这个示例中,range()只是打印数字1~4,这是你在编程语言中经常看到的差一行为的结果。函数range()让Python从你指定的第一个值开始数,并在到达你指定的第二个值后停止,因此输出不包含第二个值(这里为5)​。

4.3.2 使用range()创建数字列表

要创建数字列表,可使用函数list()将range()的结果直接转换为列表。如果将range()作为list()的参数,输出将为一个数字列表

numbers = list(range(1,6))
print(numbers)

结果:
[1,2,3,4,5]

函数range()从2开始数,然后不断地加2,直 到达到或超过终值(11),因此输出如下:

even_numbers = list(range(2,11,2))
print(even_numbers)


[2,4,6,8,10]

使用函数range()几乎能够创建任何需要的数字集,例如,如何创建一个列表,其中包含前10个整数(即1~10)的平方呢?在Python中,两个星号(**)表示乘方运算。下面的代码演示了如何将前10个整数的平方加入到一个列表中:

squares = [] ❶
for value in range(1,11):❷
    square = value**2 ❸
    squares.append(square) ❹
print(squares) ❺

[1,4,9,16,25,36,49,64,81,100]

4.3.3 对数字列表执行简单的统计计算 

 你可以轻松地找出数字列表的最大值、最小值和总和:

digits = [1,10000]

min(digits)
max(digits)
sum(digits)
print(max(digits))
print(min(digits))
print(sum(digits))

10000
1
10001

4.3.4 列表解析 

列表解析将for循环和创建新元素的代码合并成一行,并自动附加新元素。

表达式为value**2,它计算平方值。接下来,编写一个for循环,用于给表达式提供值,再加上右方括号。在这个示例中,for循环为for value in range(1,11),它将值1~10提供给表达式value**2

squares = [value**2 for value in range(1,11)]
print(squares)

[1,4,9,16,25,36,49,64,81,100]

4.3.5 练习

1.3的倍数:创建一个列表,其中包含3~30内能被3整除的数字;再使用一个for循环将这个列表中的数字都打印出来。
 

number=range(3,31,3)
for i in number:
    print(i)

2.立方:将同一个数字乘三次称为立方。例如,在Python中,2的立方用2**3表示。请创建一个列表,其中包含前10个整数(即1~10)的立方,再使用一个for循环将这些立方数都打印出来。 

num = [vlaue**3 for vlaue in range(1,11)]
print(num)

4.4 使用列表的一部分 

在本章中,你一直在学习如何处理列表的所有元素。你还可以处理列表的部分元素—Python称之为切片

4.4.1 切片

1.要创建切片,可指定要使用的第一个元素和最后一个元素的索引。与函数range()一样,Python在到达你指定的第二个索引前面的元素后停止。要输出列表中的前三个元素,需要指定索引0~3,这将输出分别为0、1和2的元素。

num = list(range(1,10))
#结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]
print(num[0:5])
#结果:[1, 2, 3, 4, 5]
print(num[1:5])
结果:[2, 3, 4, 5]

num = list(range(0,10))
print(num)
结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

2.如果你没有指定第一个索引,Python将自动从列表开头开始: 

num = list(range(0,10))
#从头开始索取
print(num[:2])
#索取到最后
print(num[2:])
#索取倒数三个
print(num[-3:])


[0, 1]
[2, 3, 4, 5, 6, 7, 8, 9]
[7, 8, 9]

 4.4.2 遍历切片

可在for循环中使用切片。

num = list(range(0,10))
for i in num[:3]:
    print(i)

0
1
2
num = list(range(0,10))
value=0
for i in num[0:4]:
    value+=i
print(value)

6

倒叙切片: 

num = [2,23,4,1,5,]
#顺序排列
num.sort()
print(num[0:2])
#倒序排列
num.sort(reverse=True)
print(num)

[1, 2]
[23, 5, 4, 2, 1]

 4.4.3 复制列表

要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引[:]

a=[1,0,2,3,12]
b=a[:]
print(a)
print(b)

a.append('23')
b.append('123')
print(a)
print(b)

[1, 0, 2, 3, 12]
[1, 0, 2, 3, 12]
[1, 0, 2, 3, 12, '23']
[1, 0, 2, 3, 12, '123']

 4.5 元组

有时候你需要创建一系列不可修改的元素,元组可以满足这种需求。Python将不能修改的值称为不可变的,而不可变的列表被称为元组。

4.5.1 定义元组

元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其元素,就像访问列表元素一样。

dimensions = (200,50) ❶
print(dimensions[0]) ❷
print(dimensions[1])

200
50

4.5.2 遍历元组中的所有值

dimensions = (200,50)
for dimension in dimensions:
    print(dimension)

200
50

4.5.3 修改元组变量 

虽然不能修改元组的元素,但可以给存储元组的变量赋值。因此,如果要修改前述矩形的尺寸,可重新定义整个元组:

dimensions = (200,50) ❶
print("Original dimensions:")
for dimension in dimensions:
    print(dimension)
dimensions = (400,100) ❷
print("\nModified dimensions:") ❸
for dimension in dimensions:
    print(dimension)

结果:
Original dimensions:
200
50
Modified dimensions:
400
100

 4.6 设置代码格式

学会编写整洁的Python后,就能明白他人编写的Python代码的整体结构—只要他们和你遵循相同的指南。要成为专业程序员,应从现在开始就遵循这些指南,以养成良好的习惯。

4.6.1 格式设置指南

若要提出Python语言修改建议,需要编写Python改进提案(Python Enhancement Proposal,PEP)。PEP 8是最古老的PEP之一,它向Python程序员提供了代码格式设置指南。PEP8的篇幅很长,但大都与复杂的编码结构相关

4.6.2 缩进

PEP 8建议每级缩进都使用四个空格,这既可提高可读性,又留下了足够的多级缩进空间。

在程序中混合使用制表符和空格可能导致极难解决的问题。如果你混合使用了制表符和空格,可将文件中所有的制表符转换为空格,大多数编辑器都提供了这样的功能。

4.6.3 行长

很多Python程序员都建议每行不超过80字符

PEP 8还建议注释的行长都不超过72字符

4.6.4 空行

用一个空行将这两部分隔开是合适的

4.6.5 其他格式设置指南

第5章if语句

5.1if 有哪些判断条件

5.1.1 基础比较运算

  • 等于==
  • 不等于!=
  • 大于>
  • 小于<
  • 大于等于>=
  • 小于等于<=

5.1.2 逻辑运算

逻辑运算能够把多个条件组合起来,形成更复杂的判断逻辑。

  • and(Python)、&&(Java、C++)
  • or(Python)、||(Java、C++)
  • not(Python)、!(Java、C++)

5.1.3 成员运算

成员运算用于判断某个值是否属于特定的集合,比如列表、字符串、字典等。

  • 属于in
  • 不属于not in
fruits = ["apple", "banana", "cherry"]
if "apple" in fruits:  # 判断列表中是否存在特定元素
    print("有苹果")
name = "Alice"
if "li" in name:  # 判断字符串中是否包含特定子串
    print("名字包含 'li'")

有苹果
名字包含 'li' 

 5.1.4身份运算

身份运算主要用于判断两个对象是否引用自同一个内存地址,也就是是否为同一个对象。

  • 是同一个对象is
  • 不是同一个对象is not

 如果错误将不会被打印

a = [1, 2, 3]
b = a
c = [1, 2, 3]
if b is a:  # b 和 a 指向同一个对象
    print("b 和 a 是同一个对象")
if c is not a:  # c 和 a 虽然值相同,但不是同一个对象
    print("c 和 a 不是同一个对象")

结果:
b 和 a 是同一个对象
c 和 a 不是同一个对象

 5.2 if-else语句

if-else语句块类似于简单的if语句,但其中的else语句让你能够指定条件测试未通过时要执行的操作。

age = 17
if age >= 18:
    print("yes")
else:
    print("no")

no

5.3 if-elif-else结构

经常需要检查超过两个的情形,为此可使用Python提供的if-elif-else结构。

age = 12
if age <4:
    price = 0
elif age <18:
    price = 5
elif age <65:
    price = 10
else:
    price = 5
print("Your admission cost is $"+str(price)+".")

5.3.1 省略else代码块 

age = 12
if age <4:
    price = 0
elif age <18:
    price = 5
elif age <65:
    price = 10
elif age >= 65:❶
    price = 5
print("Your admission cost is $"+str(price)+".")

 5.3.2 测试多个条件

有时候必须检查你关心的所有条件。在这种情况下,应使用一系列不包含elif和else代码块的简单if语句。在可能有多个条件为True,且你需要在每个条件为True时都采取相应措施时,适合使用这种方法

requested_toppings = ['mushrooms','extra cheese'] ❶
if 'mushrooms'in requested_toppings:❷
    print("Adding mushrooms.")
if 'pepperoni'in requested_toppings:❸
    print("Adding pepperoni.")
if 'extra cheese'in requested_toppings:❹
    print("Adding extra cheese.")
print("\nFinished making your pizza!")

5.4 练习

1. 外星人颜色#1:假设在游戏中刚射杀了一个外星人,请创建一个名为alien_color的变量,并将其设置为'green'、'yellow'或'red'。·编写一条if语句,检查外星人是否是绿色的;如果是,就打印一条消息,指出玩家获得了5个点。如果外星人不是绿色的,就打印一条消息,指出玩家获得了10个点。

alien_color =["green","yellow","red"]
#如果外星人是绿色的,就打印一条消息,指出玩家因射杀该外星人获得了5个点。·
# 如果外星人不是绿色的,就打印一条消息,指出玩家获得了10个点。
if "green" in alien_color:
    print("You just earned 5 points!")
else:
    print("You just earned 10 points!")

You just earned 5 points!

2.#设置变量age的值,再编写一个if-elif-else结构,
# 根据age的值判断处于人生的哪个阶段。·如果一个人的年龄小于2岁,
# 就打印一条消息,指出他是婴儿。·如果一个人的年龄为2(含)~4岁,
# 就打印一条消息,指出他正蹒跚学步。
#如果一个人的年龄为4(含)~13岁,就打印一条消息,指出他是儿童。·
# 如果一个人的年龄为13(含)~20岁,就打印一条消息,指出他是青少年。
# ·如果一个人的年龄为20(含)~65岁,就打印一条消息,指出他是成年人。·
# 如果一个人的年龄超过65(含)岁,就打印一条消息,指出他是老年人。

age=15
if age<2:
    print("你是婴儿")
elif age>=2 and age<4:
    print("你是蹒跚学步")
elif age>=4 and age<13:
    print("你是儿童")
elif age>=13 and age<18:
    print("你是青少年")
elif age>=18 and age<65:
    print("你是成年人")
elif age>=65:
    print("你是老年人")

3.# 以特殊方式跟管理员打招呼:创建一个至少包含5个用户名的列表,且其中一个用户名为'admin'
# 。想象你要编写代码,在每位用户登录网站后都打印一条问候消息。遍历用户名列表,
# 并向每位用户打印一条问候消息。·如果用户名为'admin',就打印一条特殊的问候消息,
# 如“Hello admin,would you like to see a status report?”​。·否则,打印一条普通的问候消息,
# 如“Hello Eric,thank youfor logging in again”​。

user_name = ['admin','张三','李四','王五','赵六']
for name in user_name:
    name = input("请输入用户名:")
    if name == 'admin':
        print("Hello admin,would you like to see a status report?")
    else:
        print(f"Hello {name},thank you for logging in again")

 第6章字典

在本章中,你将学习能够将相关信息关联起来的Python字典。你将学习如何访问和修改字典中的信息。鉴于字典可存储的信息量几乎不受限制,因此我们会演示如何遍历字典中的数据。另外,你还将学习存储字典的列表、存储列表的字典和存储字典的字典。理解字典后,你就能够更准确地为各种真实物体建模。你可以创建一个表示人的字典,然后想在其中存储多少信息就存储多少信息:姓名、年龄、地址、职业以及要描述的任何方面。你还能够存储任意两种相关的信息,如一系列单词及其含义,一系列人名及其喜欢的数字,以及一系列山脉及其海拔

6.1 一个简单的字典

来看一个游戏,其中包含一些外星人,这些外星人的颜色和点数各不相同。下面是一个简单的字典,存储了有关特定外星人的信息:

alien_0 = {'color':'green','points':5}
print(alien_0['color'])
print(alien_0['points'])

green
5

6.2 使用字典

6.2.1核心概念:键 — 值对的含义

  • 键(Key):是唯一的标识符,必须是不可变类型(如字符串、数字、元组),用于快速定位值。
  • 值(Value):可以是任意类型(如整数、列表、函数等),每个键对应一个值。
  • 映射关系:键和值通过冒号:关联,多个键值对用逗号,分隔,整个字典用花括号{}包裹。
student = {
    "name": "Alice",      # 键 "name" 对应值 "Alice"
    "age": 20,            # 键 "age" 对应值 20
    "grades": [90, 85, 95]  # 键 "grades" 对应值为列表
}

6.2.2字典的特点

  1. 无序性

    • 字典中的键值对没有固定顺序(Python 3.7+ 会按插入顺序保存,但不保证顺序操作)。每次遍历的顺序可能都不同。

2.键的唯一性

同一个字典中,键不能重复,重复的键会覆盖原有值

3.可变性  可以添加、修改或删除键值对。

student["age"] = 21      # 修改已有键的值
student["city"] = "New York"  # 添加新键值对
del student["grades"]    # 删除键值对

  4.键必须是不可变类型

  • 键不能是列表、字典等可变类型,因为不可哈希(无法保证唯一性)。
valid_dict = {1: "one", (1, 2): "tuple"}  # 合法:数字和元组作为键
invalid_dict = {[1]: "list"}  # 报错:列表不能作为键

 6.2.3字典的基本操作

  1. 创建字典

empty_dict = {}  # 空字典
person = {"name": "John", "age": 30}  # 直接定义
# 使用 dict() 函数创建字典
coords = dict(x=10, y=20)  
print(coords)# 输出: {'x': 10, 'y': 20}

2.访问值 

print(person["name"])  # 通过键访问值
print(person.get("age"))  # 安全访问,不存在返回 None

 3.遍历字典

for key in person:  # 遍历键
    print(key)

for value in person.values():  # 遍历值
    print(value)

for key, value in person.items():  # 遍历键值对
    print(f"{key}: {value}")

4. 检查键是否存在

if "age" in person:
    print("年龄存在")

6.2.4 字典的应用场景

  1. 数据存储:如配置文件、API 响应数据。

config = {
    "host": "localhost",
    "port": 8080,
    "debug": True
}

2.统计频率:快速记录元素出现次数。

  • freq 代表什么:它是一个字典,在这个字典里,键是单词(word),值是该单词出现的次数。
  • freq.get(word, 0) 是如何工作的
    • get() 是字典的方法,其功能是查找键所对应的值。
    • 要是字典里存在 word 这个键,就会返回该键对应的值。
    • 若字典中没有 word 键,就会返回括号里的默认值 0。
  • + 1 有什么意义:这是对获取到的值加 1,以此来统计单词的出现次数。
  • 整体逻辑是怎样的
    • 当 word 不在字典中时,会先获取默认值 0,然后加 1,也就是 freq[word] = 1
    • 当 word 已经在字典里时,就获取它当前的值,然后加 1,实现次数的更新。
words = ["apple", "banana", "apple", "cherry"]
freq = {}
for word in words:
    freq[word] = freq.get(word, 0) + 1
# 输出: {'apple': 2, 'banana': 1, 'cherry': 1}

3. 映射关系:如翻译字典、路由表。

num_to_word = {1: "一", 2: "二", 3: "三"}

6.2.5 常见错误与注意事项 

  1. 键不存在,报错

print(person["height"])  # 报错:KeyError
# 安全做法:使用 get() 方法
print(person.get("height", 0))  # 不存在返回默认值 0

2. 浅拷贝问题

  • 直接赋值会导致多个变量引用同一个字典,修改会互相影响。
a = {"x": 1}
b = a  # 浅拷贝
b["x"] = 2
print(a)  # 输出: {'x': 2}
print(b)  # 输出: {'x': 2}

6.3 嵌套

6.3.1字典列表 

下面的代码创建一个包含三个外星人的列表:

alien_0 = {'color':'green','points':5}
alien_1 = {'color':'yellow','points':10}
alien_2 = {'color':'red','points':15}
aliens = [alien_0,alien_1,alien_2] ❶
for alien in aliens:
    print(alien)

更符合现实的情形是,外星人不止三个,且每个外星人都是使用代码自动生成的。在下面的示例中,我们使用range()生成了30个外星人:

# 创建一个用于存储外星人的空列表
aliens = []
# 创建30个绿色的外星人
for alien_number in range(30):❶
    new_alien = {'color':'green','points':5,'speed':'slow'} ❷
    aliens.append(new_alien) ❸
# 显示前五个外星人
for alien in aliens[:5]:❹
    print(alien)
print("...")
# 显示创建了多少个外星人
print("Total number of aliens:"+str(len(aliens))) ❺
{'speed':'slow','color':'green','points':5}
{'speed':'slow','color':'green','points':5}
{'speed':'slow','color':'green','points':5}
{'speed':'slow','color':'green','points':5}
{'speed':'slow','color':'green','points':5}
...
Total number of aliens:30

6.3.2 在字典中存储列表 

有时候,需要将列表存储在字典中,而不是将字典存储在列表中。例如,你如何描述顾客点的比萨

# 存储所点比萨的信息
pizza = { ❶
    'crust':'thick',
    'toppings':['mushrooms','extra cheese'],
    }
# 概述所点的比萨
print("You ordered a "+pizza['crust']+"-crust pizza "+❷
    "with the following toppings:")
for topping in pizza['toppings']:❸
    print("\t"+topping)
You ordered a thick-crust pizza with the following toppings:
    mushrooms
    extra cheese

6.4.3 在字典中存储字典 

对于每位用户,我们都存储了其5项信息:名,姓,年龄,爱好,居住地;为访问这些信息,我们遍历所有的用户名,并访问与每个用户名相关联的信息字典:

user={
    'user_1':{
        'xing':'song',
        'ming':'le',
        'age':18,
        'hobby':'game',
        'city':'shanghai',
    },
    'user_2':{
        'xing':'y',
        'ming':'cy',
        'age':19,
        'hobby':'movie',
        'city':'jiangxi',
    },
}

for name,info in user.items():
    print("username:"+name)
    full_name=info['xing']+" "+info['ming']
    print("fullname:"+full_name)
    print("age:"+str(info['age']))
    print("hobby:"+info['hobby'])
    print("city:"+info['city'])
    print("------------------")


username:user_1
fullname:song le
age:18
hobby:game
city:shanghai
------------------
username:user_2
fullname:y cy
age:19
hobby:movie
city:jiangxi
------------------

6.4 练习

对一个能够以不同速度移动的外星人的位置进行跟踪。为此,我们将存储该外星人的当前速度,并据此确定该外星人将向右移动多远:

alien_0 = {'x_position':0,'y_position':25,'speed':'medium'}
print("Original x-position:"+str(alien_0['x_position']))
# 向右移动外星人
# 据外星人当前速度决定将其移动多远
if alien_0['speed'] == 'slow':
    x_increment = 1
elif alien_0['speed'] == 'medium':
    x_increment = 2
else:
    # 这个外星人的速度一定很快
    x_increment = 3
# 新位置等于老位置加上增量
alien_0['x_position'] = alien_0['x_position']+x_increment 
print("New x-position:"+str(alien_0['x_position']))

New x-position:2

第7章用户输入和while循环

7.1 函数input()的工作原理

函数input()让程序暂停运行,等待用户输入一些文本。获取用户输入后,Python将其存储在一个变量中,以方便你使用。输入存储在变量message中,接下来的print(message)将输入呈现给用户:

message = input("Tell me something,and I will repeat it back to you:")
print(message)

Tell me something,and I will repeat it back to you:Hello everyone!
Hello everyone!

7.1.1 编写清晰的程序 

有时候,提示可能超过一行,例如,你可能需要指出获取特定输入的原因。在这种情况下,可将提示存储在一个变量中,再将该变量传递给函数input()。这样,即便提示超过一行,input()语句也非常清晰。

prompt = "If you tell us who you are,we can personalize the messages you see."
prompt+= "\nWhat is your first name?"
name = input(prompt)
print("\nHello,"+name+"!")

7.1.2 使用int()来获取数值输入 

使用函数input()时,Python将用户输入解读为字符串。你试图将输入用于数值比较时(见❶)​,Python会引发错误,因为它无法将字符串和整数进行比较:

>>>age = input("How old are you?")
How old are you?21
>>>age >= 18 ❶
Traceback (most recent call last):
  File "",line 1,in 
TypeError:unorderable types:str() >= int() ❷

为解决这个问题,可使用函数int(),它让Python将输入视为数值。函数int()将数字的字符串表示转换为数值表示,如下所示:

height = input("How tall are you,in inches?")
height = int(height)
if height >= 36:
    print("\nYou're tall enough to ride!")
else:
    print("\nYou'll be able to ride when you're a little older.")

7.1.3 求模运算符

处理数值信息时,求模运算符(%)是一个很有用的工具,它将两个数相除并返回余数: 

>>>4 % 3
1
>>>5 % 3
2
>>>6 % 3
0
>>>7 % 3
1

如果一个数可被另一个数整除,余数就为0,因此求模运算符将返回0。你可利用这一点来判断一个数是奇数还是偶数

number = input("Enter a number,and I'll tell you if it's even or odd:")
number = int(number)
if number % 2 == 0:
    print("\nThe number "+str(number)+" is even.")
else:
    print("\nThe number "+str(number)+" is odd.")

7.2.1 使用while循环 

你可以使用while循环来数数,例如,下面的while循环从1数到5

current_number = 1
while current_number <= 5:
    print(current_number)
    current_number+= 1

7.2.2 让用户选择何时退出

prompt = "\nTell me something,and I will repeat it back to you:" ❶
prompt+= "\nEnter 'quit'to end the program."
message = "" ❷
while message != 'quit':❸
    message = input(prompt)
    print(message)

7.2.3 使用标志

我们将变量active设置成了True(见❶)​,让程序最初处于活动状态。这样做简化了while语句,因为不需要在其中做任何比较—相关的逻辑由程序的其他部分处理。只要变量active为True,循环就将继续运行 

prompt = "\nTell me something,and I will repeat it back to you:"
prompt+= "\nEnter 'quit'to end the program."
active = True ❶
while active:❷
    message = input(prompt)
    if message == 'quit':❸
        active = False
    else:❹
        print(message)

7.2.4 使用break退出循环

要立即退出while循环,不再运行循环中余下的代码,也不管条件测试的结果如何,可使用break语句。

prompt = "\nPlease enter the name of a city you have visited:"
prompt+= "\n(Enter 'quit'when you are finished.) "
while True:❶
    city = input(prompt)
    if city == 'quit':
        break
    else:
        print("I'd love to go to "+city.title()+"!")

7.2.5 在循环中使用continue 

要返回到循环开头,并根据条件测试结果决定是否继续执行循环,可使用continue语句,

current_number = 0
while current_number <10:
    current_number+= 1 ❶
    if current_number % 2 == 0:
        continue
    print(current_number)

7.2.6 避免无限循环 

每个while循环都必须有停止运行的途径,这样才不会没完没了地执行下去。

7.3 使用while循环来处理列表和字典

到目前为止,我们每次都只处理了一项用户信息:获取用户的输入,再将输入打印出来或作出应答;循环再次运行时,我们获悉另一个输入值并作出响应。然而,要记录大量的用户和信息,需要在while循环中使用列表和字典。for循环是一种遍历列表的有效方式,但在for循环中不应修改列表,否则将导致Python难以跟踪其中的元素。要在遍历列表的同时对其进行修改,可使用while循环。通过将while循环同列表和字典结合起来使用,可收集、存储并组织大量输入,供以后查看和显示。

7.3.1 在列表之间移动元素

假设有一个列表,其中包含新注册但还未验证的网站用户;验证这些用户后,如何将他们移到另一个已验证用户列表中呢?一种办法是使用一个while循环,在验证用户的同时将其从未验证用户列表中提取出来,再将其加入到另一个已验证用户列表中。代码可能类似于下面这样:

# 首先,创建一个待验证用户列表
# 和一个用于存储已验证用户的空列表
unconfirmed_users = ['alice','brian','candace'] ❶
confirmed_users = []
# 验证每个用户,直到没有未验证用户为止
#  将每个经过验证的列表都移到已验证用户列表中
while unconfirmed_users:❷
    current_user = unconfirmed_users.pop() ❸
    print("Verifying user:"+current_user.title())
    confirmed_users.append(current_user) ❹
# 显示所有已验证的用户
print("\nThe following users have been confirmed:")
for confirmed_user in confirmed_users:
    print(confirmed_user.title())


Verifying user:Candace
Verifying user:Brian
Verifying user:Alice
The following users have been confirmed:
Candace
Brian
Alice

7.3.2 删除包含特定值的所有列表元素 

在第3章中,我们使用函数remove()来删除列表中的特定值,这之所以可行,是因为要删除的值在列表中只出现了一次。如果要删除列表中所有包含特定值的元素,该怎么办呢?

假设你有一个宠物列表,其中包含多个值为'cat'的元素。要删除所有这些元素,可不断运行一个while循环,直到列表中不再包含值'cat',

pets = ['dog','cat','dog','goldfish','cat','rabbit','cat']
print(pets)
while 'cat'in pets:
    pets.remove('cat')
print(pets)

['dog','cat','dog','goldfish','cat','rabbit','cat']
['dog','dog','goldfish','rabbit']

7.3.3 使用用户输入来填充字典

可使用while循环提示用户输入任意数量的信息。下面来创建一个调查程序,其中的循环每次执行时都提示输入被调查者的名字和回答。我们将收集的数据存储在一个字典中,以便将回答同被调查者关联起来:

responses = {}
# 设置一个标志,指出调查是否继续
polling_active = True
while polling_active:
    # 提示输入被调查者的名字和回答
    name = input("\nWhat is your name?") ❶
    response = input("Which mountain would you like to climb someday?")
    # 将答卷存储在字典中
    responses[name] = response ❷
    # 看看是否还有人要参与调查
    repeat = input("Would you like to let another person respond?(yes/ no) ") ❸
    if repeat == 'no':
        polling_active = False
# 调查结束,显示结果
print("\n--- Poll Results ---")
for name,response in responses.items():❹
    print(name+" would like to climb "+response+".")

7.4 练习

动手试一试7-8 熟食店:创建一个名为sandwich_orders的列表,在其中包含各种三明治的名字;再创建一个名为finished_sandwiches的空列表。遍历列表sandwich_orders,对于其中的每种三明治,都打印一条消息,如I made your tuna sandwich,并将其移到列表finished_sandwiches。所有三明治都制作好后,打印一条消息,将这些三明治列出来。

7-9 五香烟熏牛肉(pastrami)卖完了:使用为完成练习7-8而创建的列表sandwich_orders,并确保'pastrami'在其中至少出现了三次。在程序开头附近添加这样的代码:打印一条消息,指出熟食店的五香烟熏牛肉卖完了;再使用一个while循环将列表sandwich_orders中的'pastrami'都删除。确认最终的列表finished_sandwiches中不包含'pastrami'。

7-10 梦想的度假胜地:编写一个程序,调查用户梦想的度假胜地。使用类似于“If you could visit one place in the world,where would you 

第8章函数

在本章中,你将学习编写函数。函数是带名字的代码块,用于完成具体的工作。要执行函数定义的特定任务,可调用该函数。需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调用执行该任务的函数,让Python运行其中的代码。你将发现,通过使用函数,程序的编写、阅读、测试和修复都将更容易。在本章中,你还会学习向函数传递信息的方式。你将学习如何编写主要任务是显示信息的函数,还有用于处理数据并返回一个或一组值的函数。最后,你将学习如何将函数存储在被称为模块的独立文件中,让主程序文件的组织更为有序。

8.1 定义函数 

下面是一个打印问候语的简单函数,名为greet_user():

def greet_user():❶
    """显示简单的问候语""" ❷
    print("Hello!") ❸
greet_user() ❹

Hello!

8.1.1 向函数传递信息 

只需稍作修改,就可以让函数greet_user()不仅向用户显示Hello!,还将用户的名字用作抬头。为此,可在函数定义def greet_user()的括号内添加username。通过在这里添加username,就可让函数接受你给username指定的任何值。现在,这个函数要求你调用它时给username指定一个值。调用greet_user()时,可将一个名字传递给它,如下所示:

def greet_user(username):
    """显示简单的问候语"""
    print("Hello,"+username.title()+"!")
greet_user('jesse')

Hello,Jesse!

8.1.2 实参和形参 

前面定义函数greet_user()时,要求给变量username指定一个值。调用这个函数并提供这种信息(人名)时,它将打印相应的问候语。在函数greet_user()的定义中,变量username是一个形参—函数完成其工作所需的一项信息。在代码greet_user('jesse')中,值'jesse'是一个实参。实参是调用函数时传递给函数的信息。我们调用函数时,将要让函数使用的信息放在括号内。在greet_user('jesse')中,将实参'jesse'传递给了函数greet_user(),这个值被存储在形参username中。

8.2 传递实参

鉴于函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参的方式很多,可使用位置实参,这要求实参的顺序与形参的顺序相同;也可使用关键字实参其中每个实参都由变量名和值组成;还可使用列表和字典。 

8.2.1 位置实参

1.函数可以多次调用。 

 2.位置实参的顺序很重要

def describe_pet(animal_type,pet_name):❶
    """显示宠物的信息"""
    print("\nI have a "+animal_type+".")
    print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('hamster','harry') ❷

 8.2.2 关键字实参

关键字实参是传递给函数的名称—值对。你直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆.

def describe_pet(animal_type,pet_name):
    """显示宠物的信息"""
    print("\nI have a "+animal_type+".")
    print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(animal_type='hamster',pet_name='harry')

8.2.3 默认值 

编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。

def describe_pet(pet_name,animal_type='dog'):
    """显示宠物的信息"""
    print("\nI have a "+animal_type+".")
    print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(pet_name='willie')

8.2.4 等效的函数调用

鉴于可混合使用位置实参、关键字实参和默认值,通常有多种等效的函数调用方式

def describe_pet(pet_name,animal_type='dog'):
# 一条名为Willie的小狗
describe_pet('willie')
describe_pet(pet_name='willie')
# 一只名为Harry的仓鼠
describe_pet('harry','hamster')
describe_pet(pet_name='harry',animal_type='hamster')
describe_pet(animal_type='hamster',pet_name='harry')

8.2.5 避免实参错误

你提供的实参多于或少于函数完成其工作所需的信息时,将出现实参不匹配错误。

8.3 返回值

函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。函数返回的值被称为返回值。在函数中,可使用return语句将值返回到调用函数的代码行。返回后就不用在用一个形参去赋值。就可以在同一个形参上做多种操作。

8.3.1 返回简单值

将结果返回到函数调用,行调用返回值的函数时,需要提供一个变量,用于存储返回的值。在这里,将返回值存储在了变量musician中(见❹)​。输出为整洁的姓名:

def get_formatted_name(first_name,last_name):❶
    """返回整洁的姓名"""
    full_name = first_name+''+last_name ❷
    return full_name.title() ❸
musician = get_formatted_name('jimi','hendrix') ❹
print(musician)

Jimi Hendrix

8.3.2 让实参变成可选的

Python将非空字符串解读为True,因此如果函数调用中提供了中间名,if middle_name将为True(

def get_formatted_name(first_name,last_name,middle_name=''):❶
    """返回整洁的姓名"""
    if middle_name:❷
        full_name = first_name+''+middle_name+''+last_name
    else:❸
        full_name = first_name+''+last_name
    return full_name.title()
musician = get_formatted_name('jimi','hendrix')
print(musician)
musician = get_formatted_name('john','hooker','lee') ❹
print(musician)

Jimi Hendrix
John Lee Hooker

 8.3.3 返回字典

我们新增了一个可选形参age,并将其默认值设置为空字符串。如果函数调用中包含这个形参的值,这个值将存储到字典中。

def build_person(first_name,last_name,age=''):
    """返回一个字典,其中包含有关一个人的信息"""
    person = {'first':first_name,'last':last_name}
    if age:
        person['age'] = age
    return person
musician = build_person('jimi','hendrix',age=27)
print(musician)

8.3.4 结合使用函数和while循环

def get_formatted_name(first_name,last_name):
    """返回整洁的姓名"""
    full_name = first_name+''+last_name
    return full_name.title()
while True:
    print("\nPlease tell me your name:")
    print("(enter 'q'at any time to quit)")
    f_name = input("First name:")
    if f_name == 'q':
        break
    l_name = input("Last name:")
    if l_name == 'q':
        break
    formatted_name = get_formatted_name(f_name,l_name)
    print("\nHello,"+formatted_name+"!")

Please tell me your name:
(enter 'q'at any time to quit)
First name:eric
Last name:matthes
Hello,Eric Matthes!
Please tell me your name:
(enter 'q'at any time to quit)
First name:q

8.4 传递列表

将列表传递给函数后,函数就能直接访问其内容。

def greet_users(names):
    """向列表中的每位用户都发出简单的问候"""
    for name in names:
        msg = "Hello,"+name.title()+"!"
        print(msg)
usernames = ['hannah','ty','margot'] ❶
greet_users(usernames)

Hello,Hannah!
Hello,Ty!
Hello,Margot!

8.4.1 在函数中修改列表 

将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。

def print_models(unprinted_designs,completed_models):❶
    """
    模拟打印每个设计,直到没有未打印的设计为止
    打印每个设计后,都将其移到列表completed_models中
    """
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        # 模拟根据设计制作3D打印模型的过程
        print("Printing model:"+current_design)
        completed_models.append(current_design)
def show_completed_models(completed_models):❷
    """显示打印好的所有模型"""
    print("\nThe following models have been printed:")
    for completed_model in completed_models:
        print(completed_model)
unprinted_designs = ['iphone case','robot pendant','dodecahedron']
completed_models = []
print_models(unprinted_designs,completed_models)
show_completed_models(completed_models)


Printing model:dodecahedron
Printing model:robot pendant
Printing model:iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case

8.4.2 禁止函数修改列表

要将列表的副本传递给函数,可以像下面这样做:

切片表示法[:]创建列表的副本。在print_models.py中,如果不想清空未打印的设计列表,可像下面这样调用print_models():

print_models(unprinted_designs[:],completed_models)

4.5 动手试一试

8-9 魔术师:创建一个包含魔术师名字的列表,并将其传递给一个名为show_magicians()的函数,这个函数打印列表中每个魔术师的名字。

8-10 了不起的魔术师:在你为完成练习8-9而编写的程序中,编写一个名为make_great()的函数,对魔术师列表进行修改,在每个魔术师的名字中都加入字样“the Great”​。调用函数show_magicians(),确认魔术师列表确实变了。

8-11 不变的魔术师:修改你为完成练习8-10而编写的程序,在调用函数make_great()时,向它传递魔术师列表的副本。由于不想修改原始列表,请返回修改后的列表,并将其存储到另一个列表中。分别使用这两个列表来调用show_magicians(),确认一个列表包含的是原来的魔术师名字,而另一个列表包含的是添加了字样“the Great”的魔术师名字。

8.5 传递任意数量的实参

下面的函数只有一个形参*toppings,但不管调用语句提供了多少实参,这个形参都将它们统统收入囊中:

def make_pizza(*toppings):
    """打印顾客点的所有配料"""
    print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')


('pepperoni',)
('mushrooms','green peppers','extra cheese')

8.5.1 结合使用位置实参和任意数量实参 

如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。

def make_pizza(size,*toppings):
    """概述要制作的比萨"""
    print("\nMaking a "+str(size)+
          "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- "+topping)
make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

Making a 16-inch pizza with the following toppings:
- pepperoni
Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

8.5.2 使用任意数量的关键字实参

需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能够接受任意数量的键—值对—调用语句提供了多少就接受多少。

def build_profile(first,last,**user_info):
    """创建一个字典,其中包含我们知道的有关用户的一切"""
    profile = {}
    profile['first_name'] = first ❶
    profile['last_name'] = last
    for key,value in user_info.items():❷
        profile[key] = value
    return profile
user_profile = build_profile('albert','einstein',
                             location='princeton',
                             field='physics')
print(user_profile)

{'first_name':'albert','last_name':'einstein',
'location':'princeton','field':'physics'}

8.5.3 动手试一试

8-12 三明治:编写一个函数,它接受顾客要在三明治中添加的一系列食材。这个函数只有一个形参(它收集函数调用中提供的所有食材)​,并打印一条消息,对顾客点的三明治进行概述。调用这个函数三次,每次都提供不同数量的实参。

8-13 用户简介:复制前面的程序user_profile.py,在其中调用build_profile()来创建有关你的简介;调用这个函数时,指定你的名和姓,以及三个描述你的键-值对。

8-14 汽车:编写一个函数,将一辆汽车的信息存储在一个字典中。这个函数总是接受制造商和型号,还接受任意数量的关键字实参。这样调用这个函数:提供必不可少的信息,以及两个名称—值对,如颜色和选装配件。这个函数必须能够像下面这样进行调用:[插图]打印返回的字典,确认正确地处理了所有的信息。

8.6 将函数存储在模块中

函数的优点之一是,使用它们可将代码块与主程序分离。通过给函数指定描述性名称,可让主程序容易理解得多。你还可以更进一步,将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。import语句允许在当前运行的程序文件中使用模块中的代码

8.6.1 导入整个模块

要让函数是可导入的,得先创建模块。模块是扩展名为.py的文件,包含要导入到程序中的代码。下面来创建一个包含函数make_pizza()的模块。为此,我们将文件pizza.py中除函数make_pizza()之外的其他代码都删除:

def make_pizza(size,*toppings):
    """概述要制作的比萨"""
    print("\nMaking a "+str(size)+
          "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- "+topping)

接下来,我们在pizza.py所在的目录中创建另一个名为making_pizzas.py的文件,这个文件导入刚创建的模块,再调用make_pizza()两次:

import pizza
pizza.make_pizza(16,'pepperoni') ❶
pizza.make_pizza(12,'mushrooms','green peppers','extra cheese')

Python读取这个文件时,代码行import pizza让Python打开文件pizza.py,并将其中的所有函数都复制到这个程序中。你看不到复制的代码,因为这个程序运行时,Python在幕后复制这些代码。你只需知道,在making_pizzas.py中,可以使用pizza.py中定义的所有函数。

如果你使用这种import语句导入了名为module_name.py的整个模块,就可使用下面的语法来使用其中任何一个函数:

module_name.function_name()

8.6.3 使用as给函数指定别名

如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名—函数的另一个名称,类似于外号。要给函数指定这种特殊外号,需要在导入它时这样做。

下面给函数make_pizza()指定了别名mp()。这是在import语句中使用make_pizza as mp实现的,关键字as将函数重命名为你提供的别名:

from pizza import make_pizza as mp
mp(16,'pepperoni')
mp(12,'mushrooms','green peppers','extra cheese')

指定别名的通用语法如下:

from module_name import function_name as new_name

 8.6.4 使用as给模块指定别名

import pizza as p
p.make_pizza(16,'pepperoni')
p.make_pizza(12,'mushrooms','green peppers','extra cheese')

8.6.5 导入模块中的所有函数

from pizza import *
make_pizza(16,'pepperoni')
make_pizza(12,'mushrooms','green peppers','extra cheese')

import语句中的星号让Python将模块pizza中的每个函数都复制到这个程序文件中。由于导入了每个函数,可通过名称来调用每个函数,而无需使用句点表示法。然而,使用并非自己编写的大型模块时,最好不要采用这种导入方法:如果模块中有函数的名称与你的项目中使用的名称相同,可能导致意想不到的结果:Python可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入所有的函数。最佳的做法是,要么只导入你需要使用的函数,要么导入整个模块并使用句点表示法。这能让代码更清晰,更容易阅读和理解。

8.7 函数编写指南

应给函数指定描述性名称,且只在其中使用小写字母和下划线。描述性名称可帮助你和别人明白代码想要做什么。给模块命名时也应遵循上述约定。

每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。文档良好的函数让其他程序员只需阅读文档字符串中的描述就能够使用它:他们完全可以相信代码如描述的那样运行;只要知道函数的名称、需要的实参以及返回值的类型,就能在自己的程序中使用它。

1.给形参指定默认值时,等号两边不要有空格:下面是错误的写法

deffunction_name(parameter_0,parameter_1='default value')

2.对于函数调用中的关键字实参,也应遵循这种约定:

8.8 动手试一试

8-15 打动手试一试模型:将示例print_models.py中的函数放在另一个名为printing_functions.py的文件中;在print_models.py的开头编写一条import语句,并修改这个文件以使用导入的函数。

8-16 导入:选择一个你编写的且只包含一个函数的程序,并将这个函数放在另一个文件中。在主程序文件中,使用下述各种方法导入这个函数,再调用它:

importmodule_name
frommodule_name importfunction_name
frommodule_name importfunction_name as fn
importmodule_name asmn
frommodule_name import *

第9章 类 

先认识面向对象的编程:

面向对象编程(Object-Oriented Programming,简称 OOP)是一种编程范式,核心思想是将程序中的数据和操作数据的方法封装在 “对象” 中,通过对象之间的交互来实现功能。它更贴近人类对现实世界的认知方式,大幅提升了代码的可复用性、可维护性和扩展性。

核心概念

  1. 对象(Object)
    现实世界中具体的事物或抽象概念的抽象,由 “属性”(数据)和 “方法”(操作数据的行为)组成。
    例如:“汽车” 可以是一个对象,属性包括颜色、型号、速度;方法包括启动、加速、刹车。

  2. 类(Class)
    对象的 “模板” 或 “蓝图”,定义了某一类对象共有的属性和方法。通过类可以创建多个具有相同结构的对象(实例)。
    例如:“汽车类” 定义了所有汽车都有的属性和方法,而 “我的红色轿车”“你的黑色 SUV” 是该类的具体实例。

  3. 封装(Encapsulation)
    将对象的属性和方法捆绑在一起,并限制外部对内部数据的直接访问,仅通过指定方法(接口)交互。
    作用:保护数据安全性,隐藏实现细节,降低代码耦合度。
    例:在 “银行账户” 类中,余额(属性)不允许直接修改,只能通过 “存款”“取款” 方法操作。

  4. 继承(Inheritance)
    一个类(子类)可以继承另一个类(父类)的属性和方法,并可添加新特性或重写父类方法。
    作用:减少代码重复,实现代码复用,体现 “is-a” 关系(如 “学生” 是 “人” 的子类)。
    例:“鸟类” 作为父类有 “飞翔” 方法,“鹰”“麻雀” 等子类继承后可直接使用该方法,也可重写为更具体的实现。

  5. 多态(Polymorphism)
    不同对象对同一操作可产生不同结果,即 “同一接口,多种实现”。
    作用:提高代码灵活性和扩展性,允许用统一的方式处理不同类型的对象。
    例:“动物” 类有 “发声” 方法,“猫” 子类实现为 “喵喵叫”,“狗” 子类实现为 “汪汪叫”,调用时无需区分具体类型,直接调用 “发声” 即可。

9.1 创建和使用类 

9.1.1 创建Dog类

 根据约定,在Python中,首字母大写的名称指的是类。

根据Dog类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下(sit())和打滚(roll_over())的能力:

class Dog():❶
    """一次模拟小狗的简单尝试""" ❷
    def __init__(self,name,age):❸
        """初始化属性name和age"""
        self.name = name ❹
        self.age = age
    def sit(self):❺
        """模拟小狗被命令时蹲下"""
        print(self.name.title()+" is now sitting.")
    def roll_over(self):
        """模拟小狗被命令时打滚"""
        print(self.name.title()+" rolled over!")

1.方法__init__()类中的函数称为方法;

你前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用方法的方式。❸处的方法__init__()是一个特殊的方法,每当你根据Dog类创建新实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。我们将方法__init__()定义成了包含三个形参:self、name和age。在这个方法的定义中,形参self必不可少,还必须位于其他形参的前面。为何必须在方法定义中包含形参self呢?因为Python调用这个__init__()方法来创建Dog实例时,将自动传入实参self。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。我们创建Dog实例时,Python将调用Dog类的方法__init__()。我们将通过实参向Dog()传递名字和年龄;self会自动传递,因此我们不需要传递它。每当我们根据Dog类创建实例时,都只需给最后两个形参(name和age)提供值。❹处定义的两个变量都有前缀self。以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。self.age = age的作用与此类似。像这样可通过实例访问的变量称为属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值