Python编程:从入门到实践-埃里克·马瑟斯

220个笔记

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

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

· 慎用小写字母l和大写字母O,因为它们可能被人错看成数字1和0。 


每个方法后面都跟着一对括号,这是因为方法通常需要额外的信息来完成其工作。这种信息是在括号内提供的。

Python使用加号(+)来合并字符串。在这个示例中,我们使用+来合并first_name、空格和last_name,以得到完整的姓名(见❶

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

使用编辑器的语法突出功能,需要输出的部分若有特殊颜色则应该检查是否是语法错误

 注意 编写程序时,编辑器的语法突出功能可帮助你快速找出某些语法错误。看到Python代码以普通句子的颜色显示,或者普通句子以Python代码的颜色显示时,就可能意味着文件中存在引号不匹配的情况。

注意 编写程序时,编辑器的语法突出功能可帮助你快速找出某些语法错误。看到Python代码以普通句子的颜色显示,或者普通句子以Python代码的颜色显示时,就可能意味着文件中存在引号不匹配的情况。

在Python 2中,无需将要打印的内容放在括号内。从技术上说,Python 3中的print是一个函数,因此括号必不可少。

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

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

如果结果出乎意料,请检查Python是否按你期望的方式将数字解读为了数值或字符串。

Python之禅

Python社区的理念都包含在Tim Peters撰写的“Python之禅”中。要获悉这些有关编写优秀Python代码的指导原则,只需在解释器中执行命令import this。

随着你对Python的认识越来越深入,并使用它来编写越来越多的代码,有一天也许会有人站在你后面惊呼:“哇,代码编写得真是漂亮!”

开发的项目涉及复杂代码时,一定要为这些代码编写有益的注释。

对,深有体会,有些功能看似非常复杂,其实把他拆分成一个个小的部分,不用想多余的东西,先尝试着去实现小的功能,慢慢写着写着灵感就喷涌而出,待所有源码都写好之后,再回过头来优化源码

 不要企图编写完美无缺的代码;先编写行之有效的代码,再决定是对其做进一步改进,还是转而去编写新代码。

不要企图编写完美无缺的代码;先编写行之有效的代码,再决定是对其做进一步改进,还是转而去编写新代码。

lstrip left左+strip脱光 right右边 他们书写时都要加上括号

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

第3章 列表简介

Python为访问最后一个列表元素提供了一种特殊语法。通过将索引指定为-1,可让Python返回最后一个列表元素:

append

如果你要从列表中删除一个元素,且不再以任何方式使用它,就使用del语句;如果你要在删除元素后还能继续使用它,就使用方法pop()。

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

注意 Python计算列表元素数时从1开始,因此确定列表长度时,你应该不会遇到差一错误。

sort(),reverse()是列表的方法,直接对原列表进行操作,sorted()是函数,其返回的是一个新的列表

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

注意 发生索引错误却找不到解决办法时,请尝试将列表或其长度打印出来。列表可能与你以为的截然不同,在程序对其进行了动态处理时尤其如此。通过查看列表或其包含的元素数,可帮助你找出这种逻辑错误。

第4章 操作列表

 在第3章,你学习了如何创建简单的列表,还学习了如何操作列表元素。在本章中,你将学习如何遍历整个列表,这只需要几行代码,无论列表有多长。循环让你能够对列表的每个元素都采取一个或一系列相同的措施,从而高效地处理任何长度的列表,包括包含数千乃至数百万个元素的列表。 4.1 遍历整个列表 你经常需要遍历列表的所有元素,对每个元素执行相同的操作。例如,在游戏中,可能需要将每个界面元素平移相同的距离;对于包含数字的列表,可能需要对每个元素执行相同的统计运算;在网站中,可能需要显示文章列表中的每个标题。

在较长的Python程序中,你将看到缩进程度各不相同的代码块,这让你对程序的组织结构有大致的认识。 当你开始编写必须正确缩进的代码时,需要注意一些常见的缩进错误。例如,有时候,程序员会将不需要缩进的代码块缩进,而对于必须缩进的代码块却忘了缩进。通过查看这样的错误示例,有助于你以后避开它们,以及在它们出现在程序中时进行修复。

Python函数range()让你能够轻松地生成一系列的数字。例如,可以像下面这样使用函数range()来打印一系列的数字:

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

在Python中,两个星号(**)表示乘方运算。

为让这些代码更简洁,可不使用临时变量square,而直接将每个计算得到的值附加到列表末尾: squares = [] for value in range(1,11): squares.append(value**2) ❶ print(squares) ❶处的代码与squares.py中❸处和❹处的代码等效。在循环中,计算每个值的平方,并立即将结果附加到列表squares的末尾。

创建更复杂的列表时,可使用上述两种方法中的任何一种。有时候,使用临时变量会让代码更易读;而在其他情况下,这样做只会让代码无谓地变长。你首先应该考虑的是,编写清晰易懂且能完成所需功能的代码;等到审核代码时,再考虑采用更高效的方法。

print(squares) 要使用这种语法,首先指定一个描述性的列表名,如squares;然后,指定一个左方括号,并定义一个表达式,用于生成你要存储到列表中的值。在这个示例中,表达式为value**2,它计算平方值。接下来,编写一个for循环,用于给表达式提供值,再加上右方括号。在这个示例中,for循环为for value in range(1,11),它将值1~10提供给表达式value**2。请注意,这里的for语句末尾没有冒号。 结果与你在前面看到的平方数列表相同:

要使用这种语法,首先指定一个描述性的列表名,如squares;然后,指定一个左方括号,并定义一个表达式,用于生成你要存储到列表中的值。在这个示例中,表达式为value**2,它计算平方值。接下来,编写一个for循环,用于给表达式提供值,再加上右方括号。在这个示例中,for循环为for value in range(1,11),它将值1~10提供给表达式value**2。请注意,这里的for语句末尾没有冒号。 结果与你

与函数range()一样,Python在到达你指定的第二个索引前面的元素后停止。要输出列表中的前三个元素,需要指定索引0~3,这将输出分别为0、1和2的元素。 下面的示例处理的是一个运动队成员列表: players.py 
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3]) ❶ ❶处的代码打印该列表的一个切片,其中只包含三名队员。输出也是一个列表,其中包含前三名队员: 

在很多情况下,切片都很有用。例如,编写游戏时,你可以在玩家退出游戏时将其最终得分加入到一个列表中。然后,为获取该玩家的三个最高得分,你可以将该列表按降序排列,再创建一个只包含前三个得分的切片。处理数据时,可使用切片来进行批量处理;编写Web应用程序时,可使用切片来分页显示信息,并在每页显示数量合适的信息。

4.4.3 复制列表 你经常需要根据既有列表创建全新的列表。下面来介绍复制列表的工作原理,以及复制列表可提供极大帮助的一种情形。 要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引([:])。这让Python创建一个始于第一个元素,终止于最后一个元素的切片,即复制整个列表。 例如,假设有一个列表,其中包含你最喜欢的三种食品,而你还想创建另一个列表,在其中包含一位朋友喜欢的所有食品。不过,你喜欢的食品,这位朋友都喜欢,因此你可以通过复制来创建这个列表:

4.5 元组 列表非常适合用于存储在程序运行期间可能变化的数据集。列表是可以修改的,这对处理网站的用户列表或游戏中的角色列表至关重要。然而,有时候你需要创建一系列不可修改的元素,元组可以满足这种需求。Python将不能修改的值称为不可变的,而不可变的列表被称为元组。 4.5.1 定义元组 元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其元素,就像访问列表元素一样。 例如,如果有一个大小不应改变的矩形,可将其长度和宽度存储在一个元组中,从而确保它们是不能修改的:

Python将不能修改的值称为不可变的,而不可变的列表被称为元组。

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

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

你在编写代码时应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。

专业程序员通常会在同一个屏幕上打开多个文件,使用标准行长可以让他们在屏幕上并排打开两三个文件时能同时看到各个文件的完整行。

PEP 8中有关行长的指南并非不可逾越的红线,有些小组将最大行长设置为99字符。在学习期间,你不用过多地考虑代码的行长,但别忘了,协作编写程序时,大家几乎都遵守PEP 8指南。在大多数编辑器中,都可设置一个视觉标志——通常是一条竖线,让你知道不能越过的界线在什么地方。

空行不会影响代码的运行,但会影响代码的可读性。Python解释器根据水平缩进情况来解读代码,但不关心垂直间距。

当前,这些指南适用的不多,但你可以大致浏览一下。 4-15 代码审核:从本章编写的程序中选择三个,根据PEP 8指南对它们进行修改。 
 ·每级缩进都使用四个空格。对你使用的文本编辑器进行设置,使其在你按Tab键时都插入四个空格;如果你还没有这样做,现在就去做吧(有关如何设置,请参阅附录B)。 ·每行都不要超过80字符。对你使用的编辑器进行设置,使其在第80个字符处显示一条垂直参考线。

你还学习了元组(它对不应变化的值提供了一定程度的保护),以及在代码变得越来越复杂时如何设置格式,使其易于阅读。 在第5章中,你将学习如何使用if语句在不同的条件下采取不同的措施;学习如何将一组较复杂的条件测试组合起来,并在满足特定条件时采取相应的措施。你还将学习如何在遍历列表时,通过使用if语句对特定元素采取特定的措施。

第5章 if语句

 编程时经常需要检查一系列条件,并据此决定采取什么措施。在Python中,if语句让你能够检查程序的当前状态,并据此采取相应的措施。 在本章中,你将学习条件测试,以检查感兴趣的任何条件。你将学习简单的if语句,以及创建一系列复杂的if语句来确定当前到底处于什么情形。接下来,你将把学到的知识应用于列表,以编写for循环,以一种方式处理列表中的大多数元素,并以另一种不同的方式处理包含特定值的元素。

在Python中检查是否相等时区分大小写,例如,两个大小写不同的值会被视为不相等: 

要判断两个值是否不等,可结合使用惊叹号和等号(!=),其中的惊叹号表示不,在很多编程语言中都如此。

1.使用and检查多个条件 要检查是否两个条件都为True,可使用关键字and将两个条件测试合而为一;如果每个测试都通过了,整个表达式就为True;如果至少有一个测试没有通过,整个表达式就为False。

为改善可读性,可将每个测试都分别放在一对括号内,但并非必须这样做。如果你使用括号,测试将类似于下面这样: 
(age_0 >= 21) and (age_1 >= 21) 2.使用or检查多个条件

要判断特定的值是否已包含在列表中,可使用关键字in。

经常需要检查超过两个的情形,为此可使用Python提供的if-elif-else结构。Python只执行if-elif-else结构中的一个代码块,它依次检查每个条件测试,直到遇到通过了的条件测试。

处的elif代码块在顾客的年龄超过65(含)时,将价格设置为5美元,这比使用else代码块更清晰些。经过这样的修改后,每个代码块都仅在通过了相应的测试时才会执行。 else是一条包罗万象的语句,只要不满足任何if或elif中的条件测试,其中的代码就会执行,这可能会引入无效甚至恶意的数据。如果知道最终要测试的条件,应考虑使用一个elif代码块来代替else代码块。这样,你就可以肯定,仅当满足相应的条件时,你的代码才会执行。


Adding mushrooms.
Finished making your pizza! 总之,如果你只想执行一个代码块,就使用if-elif-else结构;如果要运行多个代码块,就使用一系列独立的if语句。 
 动手试一试 5-3 外星人颜色#1:假设在游戏中刚射杀了一个外星人,请创建一个名为alien_color的变量,并将其设置为'green'、'yellow'或'red'。

总之,如果你在(进行条件测试时),若只想执行一个代码块,就使用if-elif-else结构;如果要运行多个代码块,就使用一系列独立的if语句。

  总之,如果你只想执行一个代码块,就使用if-elif-else结构;如果要运行多

总之,如果你只想执行一个代码块,就使用if-elif-else结构;如果要运行多个代码块,就使用一系列独立的if语句。

current_users = ['rhz','xX大','熊x二','光头强','xYxz'] #创建一个包含五个用户名,且用户名大小写都有的列表 new_users = ['RHZ','xx大','吉吉国王','超人','喜羊羊','xyxz'] #创建另一个列表,模拟注册 copy_users = [users.lower() for users in current_users] #大小写处理,把current_users全部转化为小写 #制作列表的副本,且副本中的所有元素皆为小写,解析创建列表 #副本既可以避免原列表被改变,也可以方便新注册用户与此相比较 for users in new_users: if users.lower() in copy_users: #把users转化为小写方便与副本比较 print(users+'-->用户名已经被使用') else: print(users+'-->此用户名可用!')

 5-10 检查用户名:按下面的说明编写一个程序,模拟网站确保每位用户的用户名都独一无二的方式。 ·创建一个至少包含5个用户名的列表,并将其命名为current_users。 ·再创建一个包含5个用户名的列表,将其命名为new_users,并确保其中有一两个用户名也包含在列表current_users中。 ·遍历列表new_users,对于其中的每个用户名,都检查它是否已被使用。如果是这样,就打印一条消息,指出需要输入别的用户名;否则,打印一条消息,指出这个用户名未被使用。 ·确保比较时不区分大小写;换句话说,如果用户名'John'已被使用,应拒绝用户名'JOHN'。

5-10 检查用户名:按下面的说明编写一个程序,模拟网站确保每位用户的用户名都独一无二的方式。·创建一个至少包含5个用户名的列表,并将其命名为current_users。·再创建一个包含5个用户名的列表,将其命名为new_users,并确保其中有一两个用户名也包含在列表current_users中。·遍历列表new_users,对于其中的每个用户名,都检查它是否已被使用。如果是这样,就打印一条消息,指出需要输入别的用户名;否则,打印一条消息,指出这个用户名未被使用。·确保比较时不区分大小写;换句话说,如果用户名'John'已被使用,应拒绝用户名'JOHN'。

#5-11序数 shuzi = list(range(1,10)) for num in shuzi: if num ==1 or num == 3: print(str(num)+"st") elif num == 2: print(str(num)+'nd') else: print(str(num)+'th')

 5-11 序数:序数表示位置,如1st和2nd。大多数序数都以th结尾,只有1、2和3例外。 ·在一个列表中存储数字1~9。 ·遍历这个列表。 ·在循环中使用一个if-elif-else结构,以打印每个数字对应的序数。输出内容应为1st、2nd、3rd、4th、5th、6th、7th、8th和9th,但每个序数都独占一行。

请将这方面的想法记录下来。想想你可能想编写的游戏、想研究的数据集以及想创建的Web应用程序。

第6章 字典

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

字典是一种动态结构,可随时在其中添加键—值对。要添加键—值对,可依次指定字典名、用方括号括起的键和相关联的值。

使用字典来存储用户提供的数据或在编写能自动生成大量键—值对的代码时,通常都需要先定义一个空字典。

我们还打印了x_position的初始值,旨在让用户知道这个外星人向右移动了多远。 在❶处,使用了一个if-elif-else结构来确定外星人应向右移动多远,并将这个值存储在变量x_increment中。如果外星人的速度为'slow',它将向右移动一个单位;如果速度为'medium',将向右移动两个单位;如果为'fast',将向右移动三个单位。确定移动量后,将其与x_position的当前值相加(见❷),再将结果关联到字典中的键x_position。 由于这是一个速度中等的外星人,因此其位置将向右移动两个单位:

正如你看到的,我们将一个较大的字典放在了多行中。其中每个键都是一个被调查者的名字,而每个值都是被调查者喜欢的语言。确定需要使用多行来定义字典时,在输入左花括号后按回车键,再在下一行缩进四个空格,指定第一个键—值对,并在它后面加上一个逗号。此后你再次按回车键时,文本编辑器将自动缩进后续键—值对,且缩进量与第一个键—值对相同。

注意,即便遍历字典时,键—值对的返回顺序也与存储顺序不同。Python不关心键—值对的存储顺序,而只跟踪键和值之间的关联关系。

在不需要使用字典中的值时,方法keys()很有用。下面来遍历字典favorite_languages,并将每个被调查者的名字都打印出来:

如果显式地使用方法keys()可让代码更容易理解,你可以选择这样做,但如果你愿意,也可省略它。

if name in friends: ❷
 print(" Hi "+name.title()+
 ", I see your favorite language is "+
 favorite_languages[name].title()+"!") ❸ 在❶处,我们创建了一个列表,其中包含我们要通过打印消息,指出其喜欢的语言的朋友。在循环中,我们打印每个人的名字,并检查当前的名字是否在列表friends中(见❷)。如果在列表中,就打印一句特殊的问候语,其中包含这位朋友喜欢的语言。为访问喜欢的语言,我们使用了字典名,并将变量name的当前值作为键(见❸)。每个人的名字都会被打印,但只对朋友打印特殊消息:

为剔除重复项,可使用集合(set)。集合类似于列表,但每个元素都必须是独一无二的

通过对包含重复元素的列表调用set(),可让Python找出列表中独一无二的元素,并使用这些元素来创建一个集合。在❶处,我们使用了set()来提取favorite_languages.values()中不同的语言。

#6-5河流 rivers = { '尼罗河' : '埃及',#","不要忘记了 '长江' : '中国', '密西西比河' :"美国" } for river in rivers.keys(): print(river+'流经'+rivers[river]+'\n') best_river =['长江'] for river in rivers.keys(): if river in best_river: print('世界上最好的国家'+rivers[river]+', 有最受世界欢迎的河流'+river+'!\n') else: print('对不起:'+rivers[river]+',请继续努力!和你们的河流:'+river+'一起!\n')

 6-6 调查:在6.3.1节编写的程序favorite_languages.py中执行以下操作。 ·创建一个应该会接受调查的人员名单,其中有些人已包含在字典中,而其他人未包含在字典中。 ·遍历这个人员名单,对于已参与调查的人,打印一条消息表示感谢。对于还未参与调查的人,打印一条消息邀请他参与调查。

在❶处,range()返回一系列数字,其唯一的用途是告诉Python我们要重复这个循环多少次。

alien['color'] = 'yellow' alien['speed'] = 'medium' alien['points'] = 10

不要放弃哦,仔细看看我的参考参考!加油! #使用range()生成30个外星人 #创建一个用于存储外星人的空列表 aliens = [] #创建30个绿色的外星人 for alien_number in range(30): #range()返回一系列数字,其唯一的用途是告诉Python我们要重复这个循环多少次。 #range(30)默认从0开始,打印0-29,共30个数 #若没有print(value)那么就是循环了30次 new_alien = { '颜色:':'绿色', '击杀所得分数':'5' '移动速度':'慢'} aliens.append(new_alien) #每循环一次就在列表末尾添加一个机器人 # 使用切片打印显示前五个外星人 for alien in aliens [:5]: print(alien) #注意啦,如果你手动打印一下这个被加入列表的字典你就会发现他其实就是列表里面嵌套的字典如: print(alien) #输出: [{'颜色': '绿色', '击杀所得分数': '5'}, {'颜色': '黄色', '击杀所得分数': '10'}, {'颜色': '红色', '击杀所得分数': '15'}] print('...') # 显示创建了多少个外星人 print('外星人的个数:'+str(len(aliens))) ##将前三个外星人更改 for alien in aliens[:3]: if alien['颜色'== '绿色']: alien['cocor'] = '红色' #就算被存入列表,他也是一个字典,单独访问修改其中元素,就直接用修改字典的方法: 因为此处的alien就是指向列表中的字典,而修改字典就应该是alien[键]=‘xx ’; 加油,欢迎和我讨论!

 鉴于我们要修改前三个外星人,需要遍历一个只包含这些外星人的切片。当前,所有外星人都是绿色的,但情况并非总是如此,因此我们编写了一条if语句来确保只修改绿色外星人。如果外星人是绿色的,我们就将其颜色改为'yellow',将其速度改为'medium',并将其点数改为10,如下面的输出所示:

shopping = { '商品': ['凉面','米粉','面条','粥'], '口味': ['辣', '清淡','微辣','辣'] } # 概述所点的菜 for shop in shopping['商品']: print("你点了一份 "+shop+"! "+ "我们有这些口味:") for taste in shopping['口味']: print("\t"+taste)

 # 存储所点比萨的信息 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)

可在字典中嵌套字典,但这样做时,代码可能很快复杂起来。例如,如果有多个网站

第7章 用户输入和while循环

[插图] 大多数程序都旨在解决最终用户的问题,为此通常需要从用户那里获取一些信息。例如,假设有人要判断自己是否到了投票的年龄,要编写回答这个问题的程序,就需要知道用户的年龄,这样才能给出答案。因此,这种程序需要让用户输入其年龄,再将其与投票年龄进行比较,以判断用户是否到了投票的年龄,再给出结果。 在本章中,你将学习如何接受用户输入,让程序能够对其进行处理。在程序需要一个名字时,你需要提示用户输入该名字;程序需要一个名单时,你需要提示用户输入一系列名字。为此,你需要使用函数input()。 你还将学习如何让程序不断地运行,让用户能够根据需要输入信息,并在程序中使用这些信息。为此,你需要使用while循环让程序不断地运行,直到指定的条件不满足为止。

你需要使用函数input()。

使用函数input()时,Python将用户输入解读为字符串。

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

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

偶数都能被2整除,因此对一个数(number)和2执行求模运算的结果为零,即number % 2 == 0,那么这个数就是偶数;否则就是奇数。

循环中的代码打印current_number的值,再使用代码current_number+= 1(代码current_number = current_number+1的简写)将其值加1。

理解为满足条件表达式时python返回True,不满足时python返回False就好,while Ture继续循环,while False结束循环

 current_number大于5,循环将停止,整个程序也将到此结束:

理解为满足条件表达式时python返回True,不满足时python返回False就好,while Ture继续循环,while False结束循环

 current_number大于5,循环将停止,整个程序也将到此结束:

Python首次执行while语句时,需要将message的值与'quit'进行比较,但此时用户还没有输入。如果没有可供比较的东西,Python将无法继续运行程序。为解决这个问题,我们必须给变量message指定一个初始值。虽然这个初始值只是一个空字符串,但符合要求,让Python能够执行while循环所需的比较。只要message的值不是'quit',这个循环(见❸)就会不断运行。

这个程序很好,唯一美中不足的是,它将单词'quit'也作为一条消息打印了出来。为修复这种问题,只需使用一个简单的if测试:

在要求很多条件都满足才继续运行的程序中,可定义一个变量,用于判断整个程序是否处于活动状态。这个变量被称为标志,充当了程序的交通信号灯。你可让程序在标

程序在标志为True时继续运行,并在任何事件导致标志的值为False时让程序停止运行。这样,在while语句中就只需检查一个条件——标志的当前值是否为True,

使用break退出循环

注意 在任何Python循环中都可使用break语句。例如,可使用break语句来退出遍历列表或字典的for循环。

7.2.5 在循环中使用continue 要返回到循环开头,并根据条件测试结果决定是否继续执行循环,可使用continue语句,它不像break语句那样不再执行余下的代码并退出整个循环。例如,来看一个从1数到10,但只打印其中奇数的循环: counting.py 
current_number = 0
while current_number < 10:
 current_number+= 1 ❶
 if current_number % 2 == 0:
 continue
 print(current_number)

continue语句,让Python忽略余下的代码,并返回到循环的开头。如果当前的数字不能被2整除,就执行循环中余下的代码,Python将这个数字打印出来:

7-5 电影票:有家电影院根据观众的年龄收取不同的票价:不到3岁的观众免费;3~12岁的观众为10美元;超过12岁的观众为15美元。请编写一个循环,在其中询问用户的年龄,并指出其票价。 7-6 三个出口:以另一种方式完成练习7-4或练习7-5,在程序中采取如下所有做法。 ·在while循环中使用条件测试来结束循环。 ·使用变量active来控制循环结束的时机。 ·使用break语句在用户输入'quit'时退出循环。 7-7 无限循环:编写一个没完没了的循环,并运行它(要结束该循环,可按Ctrl+C,也可关闭显示输出的窗口)。 7.3 使用while循环来处理列表和字典 到目前为止,我们每次都只处理了一项用户信息:获取用户的输入,再将输入打印出来或作出应答;循环再次运行时,我们获悉另一个输入值并作出响应。然而,要记录大量的用户和信息,需要在while循环中使用列表和字典。

active = True while active: prompet = '请输入你的年龄查询你的票价!' age = int(input(prompet)) if (age < 3) and (age > 0): price = 0 elif (age >3) and (age <12): price = 10 else: price = 15 print('你好朋友你的票价是: '+str(price)) K = input("输入quit结束,输入其他继续") if K == 'quit': break

 7-5 电影票:有家电影院根据观众的年龄收取不同的票价:不到3岁的观众免费;3~12岁的观众为10美元;超过12岁的观众为15美元。请编写一个循环,在其中询问用户的年龄,并指出其票价。

for循环是一种遍历列表的有效方式,但在for循环中不应修改列表,否则将导致Python难以跟踪其中的元素。要在遍历列表的同时对其进行修改,可使用while循环。

只要polling_active为True,Python就运行while循环中的代码。 在这个循环中,提示用户输入其用户名及其喜欢爬哪座山(见❶)。将这些信息存储在字典responses中(见❷),然后询问用户调查是否继续(见❸)。如果用户输入yes,程序将再次进入while循环;如果用户输入no,标志polling_active将被设置为False,而while循环将就此结束。最后一个代码块(见❹)显示调查结果。 如果你运行这个程序,并输入一些名字和回答,输出将类似于下面这样: 
What is your name?Eric
Which mountain would you like to climb someday?Denali
Would you like to let another person respond?

responses[neam]=response 在字典中其实是 responses={ 'neam':'response' }

 在这个循环中,提示用户输入其用户名及其喜欢爬哪座山(见❶)。将这些信息存储在字典responses中(见❷),然后询问用户调查是否继续(见❸)。如果用户输入yes,程序将再次进入while循环;如果用户输入no,标志polling_active将被设置为False,而while循环将就此结束。最后一个代码块(见❹)显示调查结果。

在这个循环中,提示用户输入其用户名及其喜欢爬哪座山(见❶)。将这些信息存储在字典responses中(见❷),然后询问用户调查是否继续(见❸)。如果用户输入yes,程序将再次进入while循环;如果用户输入no,标志polling_active将被设置为False,而while循环将就此结束。最后一个代码块(见❹)显示调查结果。

places = {} go = [] while True: name = input('你叫啥名字?') while True: place = input('你最想要去的地方?') go.append(place) continue_place = input('是否还有其他地方?yes/no') if continue_place == 'no': break places[name] = go#存入字典 again = input('是否退出?yes/no') if again == 'yes': break for name,place in places.items(): print(name+'最想去的地方是:\n') print(place)

 7-10 梦想的度假胜地:编写一个程序,调查用户梦想的度假胜地。使用类似于“If you could visit one place in the world, where would you go?”的提示,并编写一个打印调查结果的代码块。

第8章 函数

在函数greet_user()的定义中,变量username是一个形参——函数完成其工作所需的一项信息。在代码greet_user('jesse')中,值'jesse'是一个实参。实参是调用函数时传递给函数的信息。我们调用函数时,将要让函数使用的信息放在括号内。在greet_user('jesse')中,将实参'jesse'传递给了函数greet_user(),这个值被存储在形参username中。

为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。

关键字实参的顺序无关紧要,因为Python知道各个值该存储到哪个形参中。

例如,如果你发现调用describe_pet()时,描述的大都是小狗,就可将形参animal_type的默认值设置为'dog'。

使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参。这让Python依然能够正确地解读位置实参。

Traceback (most recent call last): File "pets.py", line 6, in ❶ describe_pet() ❷TypeError: describe_pet() missing 2 required positional arguments: 'animal_ ❸type' and 'pet_name'

函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。函数返回的值被称为返回值。在函数中,可使用return语句将值返回到调用函数的代码行。返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。

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+"!") 我们添加了一条消息来告诉用户如何退出,然后在每次提示用户输入时,都检查他输入的是否是退出值,如果是,就退出循环。现在,这个程序将不断地问候,直到用户输入的姓或名为'q'为止: 
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)

如果调用这个函数时指定了歌曲数,就将这个值添加到表示专辑的字典中。调用这个函数,并至少在一次调用中指定专辑包含的歌曲数。 8-8 用户的专辑:在为完成练习8-7编写的程序中,编写一个while循环,让用户输入一个专辑的歌手和名称。获取这些信息后,使用它们来调用函数make_album(),并将创建的字典打印出来。在这个while循环中,务必要提供退出途径。 8.4 传递列表 你经常会发现,向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象(如字典)。将列表传递给函数后,函数就能直接访问其内容。下面使用函数来提高处理列表的效率。 假设有一个用户列表,我们要问候其中的每位用户。下面的示例将一个名字列表传递给一个名为greet_users()的函数,这个函数问候列表中的每个人:

原来的要求每调用一次函数,字典就刷新一次,拓展是每一次存储都具有记忆性,更符合现实生活中的实际要求 c_singer = {}#存储歌手名字 a_album ={}#存储歌手专辑 def make_album(name,album_name): names=name while True: c = [] c.append(album_name) b = input('请输入该歌手的更多专辑名') c.append(b) a_album[names]= c print(b+'已经存储,输入q退出') c = input('\n请输入:') if c == 'q': break c_singer[names]=a_album[names] while True: h=input('是否退出yes/no') if h == 'yes': break e = input('请输入歌手名字:') f = input('请输入专辑名字') make_album(e,f) for singer_name,singer_album in c_singer.items(): print(singer_name+'的专辑有:'+'\n') print(singer_album) print('\n')

 8-8 用户的专辑:在为完成练习8-7编写的程序中,编写一个while循环,让用户输入一个专辑的歌手和名称。获取这些信息后,使用它们来调用函数make_album(),并将创建的字典打印出来。在这个while循环中,务必要提供退出途径。

描述性的函数名让别人阅读这些代码时也能明白,虽然其中没有任何注释。相比于没有使用函数的版本,这个程序更容易扩展和维护。

这个程序还演示了这样一种理念,即每个函数都应只负责一项具体的工作。第一个函数打印每个设计,而第二个显示打印好的模型;这优于使用一个函数来完成两项工作。编写函数时,如果你发现它执行的任务太多,请尝试将这些代码划分到两个函数中。别忘了,总是可以在一个函数中调用另一个函数,这有助于将复杂的任务划分成一系列的步骤。

形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中。函数体内的print语句通过生成输出来证明Python能够处理使用一个值调用函数的情形,也能处理使用三个值来调用函数的情形

注意,Python将实参封装到一个元组中,即便函数只收到一个值也如此:

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

形参**user_info中的两个星号让Python创建一个名为user_info的空字典,并将收到的所有名称—值对都封装到这个字典中。

给形参指定默认值时,等号两边不要有空格:

如果程序或模块包含多个函数,可使用两个空行将相邻的函数分开,这样将更容易知道前一个函数在什么地方结束,下一个函数从什么地方开始。

动手试一试 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

如何编写函数,以及如何传递实参,让函数能够访问完成其工作所需的信息;如何使用位置实参和关键字实参,以及如何接受任意数量的实参;显示输出的函数和返回值的函数;如何将函数同列表、字典、if语句和while循环结合起来使用。你还知道了如何将函数存储在被称为模块的独立文件中,让程序文件更简单、更易于理解。最后,你学习了函数编写指南,遵循这些指南可让程序始终结构良好,并对你和其他人来说易于阅读。

第9章 类

首字母大写的名称指的是类。这个类定义中的括号是空的,因为我们要从空白创建这个类。

Python先找到实例my_dog,再查找与这个实例相关联的属性name

输出是有关my_dog的摘要: 
My dog's name is Willie.
My dog is 6 years old. 2.调用方法 根据Dog类创建实例后,就可以使用句点表示法来调用Dog类中定义的任何方法。下面来让小狗蹲下和打滚: 
class Dog():
 --snip--
my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over() 要调用方法,可指定实例的名称(这里是my_dog)和要调用的方法,并用句点分隔它们。遇到代码my_dog.sit()时,Python在类Dog中查找方法sit()并运行其代码。

Lucy is now sitting. 就算我们给第二条小狗指定同样的名字和年龄,Python依然会根据Dog类创建另一个实例。你可按需求根据一个类创建任意数量的实例,条件是将每个实例都存储在不同的变量中,或占用列表或字典的不同位置。 
 动手试一试 9-1 餐馆:创建一个名为Restaurant的类,其方法__init__()设置两个属性:restaurant_name和cuisine_type。创建一个名为describe_restaurant()的方法和一个名为open_restaurant()的方法,其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。

Python将创建一个名为odometer_reading的属性,并将其初始值设置为0(见❶)

我们可以通过在属性前加下划线让对方无法直接修改 class V: def __init__(self, x): self._x = x

 你可以使用类似于上面的方法来控制用户修改属性值(如里程表读数)的方式,但能够访问程序的人都可以通过直接访问属性来将里程表修改为任何值。要确保安全,除了进行类似于前面的基本检查外,还需特别注意细节。

 你可以使用类似于上面的方法来控制用户修改属性值(如里程表读数)的方式,但能够访问程序的人都可以通过直接访问属性来将里程表修改为任何值。要确保安全,除了进行类似于前面的基本检查外,还需特别注意细节。

9-5 尝试登录次数:在为完成练习9-3而编写的User类中,添加一个名为login_attempts的属性。编写一个名为increment_login_attempts()的方法,它将属性login_attempts的值加1。再编写一个名为reset_login_attempts()的方法,它将属性login_attempts的值重置为0。 根据User类创建一个实例,再调用方法increment_login_attempts()多次。打印属性login_attempts的值,确认它被正确地递增;然后,调用方法reset_login_attempts(),并再次打印属性login_attempts的值,确认它被重置为0。 9.3 继承

编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

根据ElectricCar类创建的所有实例都将包含这个属性,但所有Car实例都不包含它。

对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

"""电动汽车的独特之处""" def __init__(self, make, model, year): """ 初始化父类的属性,再初始化电动汽车特有的属性 """ super().__init__(make, model, year) self.battery = Battery() ❹ my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name()) my_tesla.battery.describe_battery() 在❶处,我们定义了一个名为Battery的新类,它没有继承任何类。❷处的方法__init__()除self外,还有另一个形参battery_size。这个形参是可选的:如果没有给它提供值,电瓶容量将被设置为70。方法describe_battery()也移到了这个类中(见❸)。 在ElectricCar类中,我们添加了一个名为self.battery的属性(见❹)。这行代码让Python创建一个新的Battery实例(由于没有指定尺寸,因此为默认值70),并将该实例存储在属性self.battery中。每当方法__init__()被调用时,都将执行该操作;因此现在每个ElectricCar实例都包含一个自动创建的Battery实例。

1.你用类创建了一个实例 2.你要把自己提供的信息交给类处理,但是世界那么大怎么防止误入花花世界呢? 3.self标识帮助你找到正确的地方,然后后面跟上形参你赋值交信息给他自动处理 4.你创建了个电瓶车的类,你确不知道他的电池是几号,难道你每次创建电瓶车都要再去写一大串代码问问咱的电瓶车几号电池?咋就是说不用呀,直接给所有型号的电池找个家,创建一个电池类不就得了 5.如果说单独创建个电池类你嫌每次都要单独再去给电瓶车创建电池类再访问里面的属性和方法太麻烦,你直接把他当作电瓶车的属性不就得了,每次只要通过类创建实例,self当作你的路标,句号表示法当作你们的交流工具,你只管疯狂赋值不就o了? class Battery(): def __init__(self,battery_size): self.size = battery_size def dcxh(self): print('俺是'+self.size+'型号的老铁!') dc_1 = Battery('大号‘) print(dc_1.dcxh()) dc_1 = ElectricCar('中国', '兰博基尼', 1200) dc_1.get_descriptive_name() #用作电瓶的属性 class ElectricCar(Car): """电动汽车的独特之处""" def __init__(self, make, model, year): """ 初始化父类的属性,再初始化电动汽车特有的属性 """ super().__init__(make, model, year) self.battery = Battery() --snip-- dc_1 = ElectricCar('中国','兰博基尼',‘1200’) dc_1.battery.dcxh() dc_1.get_descriptive_name() 如果只是创建电池类的话我要调用这些东西,还要反复的创建类,用作属性的话只需要创建一次类,就可通过句号访问属性来调用电池类里面的方法了,如果实例不用作属性,一次创建可能不算什么,但是批量的话就严重的浪费资源,而且后期维护也比较累

 在ElectricCar类中,我们添加了一个名为self.battery的属性(见❹)。这行代码让Python创建一个新的Battery实例(由于没有指定尺寸,因此为默认值70),并将该实例存储在属性self.battery中。每当方法__init__()被调用时,都将执行该操作;因此现在每个ElectricCar实例都包含一个自动创建的Battery实例。

在ElectricCar类中,我们添加了一个名为self.battery的属性(见❹)。这行代码让Python创建一个新的Battery实例(由于没有指定尺寸,因此为默认值70),并将该实例存储在属性self.battery中。每当方法__init__()被调用时,都将执行该操作;因此现在每个ElectricCar实例都包含一个自动创建的Battery实例。

这让你进入了程序员的另一个境界:解决上述问题时,你从较高的逻辑层面(而不是语法层面)考虑;你考虑的不是Python,而是如何使用代码来表示实物。到达这种境界后,你经常会发现,现实世界的建模方法并没有对错之分。有些方法的效率更高,但要找出效率最高的表示法,需要经过一定的实践。只要代码像你希望的那样运行,就说明你做得很好!即便你发现自己不得不多次尝试使用不同的方法来重写类,也不必气馁;要编写出高效、准确的代码,都得经过这样的过程。

class Canguan(): def __init__(self,cg_name,cg_type): self.name = cg_name self.type = cg_type def describe_cg(self): print('我们的餐馆:'+self.name+'正在营业') class IceCreamStand(Canguan): def __init__(self,cg_name,cg_type): super().__init__(cg_name,cg_type) self.flavors = ['草莓','芒果'] def icecream(self): for icecream_1 in self.flavors: print('你点哪个?我们有如下口味冰淇淋:') print(icecream_1) print(self.flavors) ice = IceCreamStand('巴费克','国际') ice.describe_cg() print(ice.name+ice.type) ice.icecream() print('\n') print(ice.flavors)

 9-6 冰淇淋小店:冰淇淋小店是一种特殊的餐馆。编写一个名为IceCreamStand的类,让它继承你为完成练习9-1或练习9-4而编写的Restaurant类。这两个版本的Restaurant类都可以,挑选你更喜欢的那个即可。添加一个名为flavors的属性,用于存储一个由各种口味的冰淇淋组成的列表。编写一个显示这些冰淇淋的方法。创建一个IceCreamStand实例,并调用这个方法。

class User(): def __init__(self,first_name,last_name,age,location): self.fname = first_name self.lname = last_name self.age = age self.dz = location def ms_user(self): print('您好 '+self.fname +'先生!') print('您的地址是:'+self.dz) print('你今年的岁数是:'+str(self.age)) def greet_user(self): fullname = self.fname+self.lname print('你好:'+fullname+'先生!') class Admin(User): def __init__(self,first_name,last_name,age=30,location='中国'): super().__init__(first_name,last_name,age,location) self.qx=Privileges() #self.privileges = ['can add post',"can delete post","can ban user"] #def show_qx(self): #print('管理员admin的权限是:') #print(self.privileges) class Privileges(): def __init__(self): self.privileges = ['can add post',"can delete post","can ban user"] def show_qx(self): print('管理员admin的权限是:') print(self.privileges) admin_1 = Admin('周','杰伦') admin_1.qx.show_qx() admin_1.ms_user() admin_1.greet_user()

 9-8 权限:编写一个名为Privileges的类,它只有一个属性——privileges,其中存储了练习9-7所说的字符串列表。将方法show_privileges()移到这个类中。在Admin类中,将一个Privileges实例用作其属性。创建一个Admin实例,并使用方法show_privileges()来显示其权限。

将方法show_privileges()移到这个类中。在Admin类中,将一个Privileges实例用作其属性。创建一个Admin实例,并使用方法show_privileges()来显示其权限。 9-9 电瓶升级:在本节最后一个electric_car.py版本中,给Battery类添加一个名为upgrade_battery()的方法。这个方法检查电瓶容量,如果它不是85,就将它设置为85。创建一辆电瓶容量为默认值的电动汽车,调用方法get_range(),然后对电瓶进行升级,并再次调用get_range()。你会看到这辆汽车的续航里程增加了。 9.4 导入类 随着你不断地给类添加功能,文件可能变得很长,即便你妥善地使用了继承亦如此。

9.4.6 在一个模块中导入另一个模块 有时候,需要将类分散到多个模块中,以免模块太大,或在同一个模块中存储不相关的类。将类存储在多个模块中时,你可能会发现一个模块中的类依赖于另一个模块中的类。在这种情况下,可在前一个模块中导入必要的类。 例如,下面将Car类存储在一个模块中,并将ElectricCar和Battery类存储在另一个模块中。我们将第二个模块命名为electric_car.py(这将覆盖前面创建的文件electric_car.py),并将Battery和ElectricCar类复制到这个模块中: electric_car.py 
"""一组可用于表示电动汽车的类"""
from car import Car ❶

先找出让你能够编写出可行代码的方式,再尝试让代码更为组织有序。 动手试一试 9-10 导入Restaurant类:将最新的Restaurant类存储在一个模块中。在另一个文件中,导入Restaurant类,创建一个Restaurant实例,并调用Restaurant的一个方法,以确认import语句正确无误。 9-11 导入Admin类:以为完成练习9-8而做的工作为基础,将User、Privileges和Admin类存储在一个模块中,再创建一个文件,在其中创建一个Admin实例并对其调用方法show_privileges(),以确认一切都能正确地运行。 9-12 多个模块:将User类存储在一个模块中,并将Privileges和Admin类存储在另一个模块中。再创建一个文件,在其中创建一个Admin实例,并对其调用方法show_privileges(),以确认一切都依然能够正确地运行。 9.5 Python标准库

from random import randint class Die(): def __init__(self,sides = 6,tz_cs = 1 ): self.sides = sides self.cs = tz_cs def roll_die(self,tz_cs): #返回一个1,y的随机数 a = [] for i in range(0,tz_cs): x = randint(1,self.sides) a.append(x) print(a) tz_6 = Die(6) tz_6.roll_die(10)

 模块random包含以各种方式生成随机数的函数,其中的randint()返回一个位于指定范围内的整数,例如,下面的代码返回一个1~6内的整数:

创建一个6面的骰子,再掷10次。创建一个10面的骰子和一个20面的骰子,并将它们都掷10次。 9-15 Python Module of the Week:要了解Python标准库,一个很不错的资源是网站Python Module of the Week。请访问http://pymotw.com/并查看其中的目录,在其中找一个你感兴趣的模块进行探索,或阅读模块collections和random的文档。 9.6 类编码风格 你必须熟悉有些与类相关的编码风格问题,在你编写的程序较复杂时尤其如此。 类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。

创建一个10面的骰子和一个20面的骰子,并将它们都掷10次。 9-15 Python Module of the Week:要了解Python标准库,一个很不错的资源是网站Python Module of the Week。请访问http://pymotw.com/并查看其中的目录,在其中找一个你感兴趣的模块进行探索,或阅读模块collections和random的文档。 9.6 类编码风格 你必须熟悉有些与类相关的编码风格问题,在你编写的程序较复杂时尤其如此。 类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。 对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。

第10章 文件和异常

关键字with在不再需要访问文件后将其关闭。在这个程序中,注意到我们调用了open(),但没有调用close();你也可以调用open()和close()来打开和关闭文件,但这样做时,如果程序存在bug,导致close()语句未执行,文件将不会关闭。这看似微不足道,但未妥善地关闭文件可能会导致数据丢失或受损。

Python方法rstrip()删除(剥除)字符串末尾的空白

此方法删除的并不是永久删除,只是输出的删除了,需要注意

 Python方法rstrip()删除(剥除)字符串末尾的空白。

with open(filename) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string+= line.strip() print(pi_string) print(len(pi_string)) 这样,我们就获得了一个这样的字符串:它包含精确到30位小数的圆周率值。这个字符串长32字符,因为它还包含整数部分的3和小数点: 3.141592653589793238462643383279 32 注意 读取文本文件时,Python将其中的所有文本都解读为字符串。如果你读取的是数字,并要将其作为数值使用,就必须使用函数int()将其转换为整数,或使用函数float()将其转换为浮点数。 10.1.6 包含一百万位的大型文件 前面我们分析的都是一个只有三行的文本文件,但这些代码示例也可处理大得多的文件。如果我们有一个文本文件,其中包含精确到小数点后1000000位而不是30位的圆周率值,也可创建一个包含所有这些数字的字符串。

大家如果出现编码错误可以: 按行读取文本文件时报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position... python的open方法默认编码取决于平台,如果是windows平台,默认编码是gbk,如果文件是utf8编码,就会报这个错误。 解决办法: with open("input.txt",encoding='utf-8') as f: for line in f: print(line)

 Python学习笔记:在文本编辑器中新建一个文件,写几句话来总结一下你至此学到的Python知识,其中每一行都以“In Python you can”打头。将这个文件命名为learning_python.txt,并将其存储到为完成本章练习而编写的程序所在的目录中。编写一个程序,它读取这个文件,并将你所写的内容打印三次:第一次打印时读取整个文件;第二次打印时遍历文件对象;第三次打印时将各行存储在一个列表中,再在with代码块外打印它们。

10-2 C语言学习笔记:可使用方法replace()将字符串中的特定单词都替换为另一个单词。下面是一个简单的示例,演示了如何将句子中的'dog'替换为'cat': >>> message = "I really like dogs." >>> message.replace('dog', 'cat') 'I really like cats.' 读取你刚创建的文件learning_python.txt中的每一行,将其中的Python都替换为另一门语言的名称,如C。将修改后的各行都打印到屏幕上。 10.2 写入文件 保存数据的最简单的方式之一是将其写入到文件中。通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在:你可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。

try: 工程(预测的可能发生错误的代码) except: try代码块错误时的方法 else: try代码块成功执行时运行

 try-except-else代码块的工作原理大致如下:Python尝试执行try代码块中的代码;只有可能引发异常的代码才需要放在try语句中。有时候,有一些仅在try代码块成功执行时才需要运行的代码;这些代码应放在else代码块中。except代码块告诉Python,如果它尝试运行try代码块中的代码时引发了指定的异常,该怎么办。

你可以分析包含整本书的文本文件。很多经典文学作品都是以简单文本文件的方式提供的,因为它们不受版权限制。

txt', 'little_women.txt'] for filename in filenames: count_words(filename) 相比于前一个程序,这个程序唯一不同的地方是❶处的pass语句。现在,出现FileNotFoundError异常时,将执行except代码块中的代码,但什么都不会发生。这种错误发生时,不会出现traceback,也没有任何输出。用户将看到存在的每个文件包含多少个单词,但没有任何迹象表明有一个文件未找到: The file alice.txt has about 29461 words. The file moby_dick.txt has about 215136 words. The file little_women.txt has about 189079 words. pass语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,并且以后也许要在这里做些什么。例如,在这个程序中,我们可能决定将找不到的文件的名称写入到文件missing_files.txt中。用户看不到这个文件,但我们可以读取这个文件,进而处理所有文件找不到的问题。 10.3.9 决定报告哪些错误

org/),并找一些你想分析的图书。下载这些作品的文本文件或将浏览器中的原始文本复制到文本文件中。 你可以使用方法count()来确定特定的单词或短语在字符串中出现了多少次。例如,下面的代码计算'row'在一个字符串中出现了多少次: >>line = "Row, row, row your boat" >>line.count('row') 2 >>line.lower().count('row') 3 请注意,通过使用lower()将字符串转换为小写,可捕捉要查找的单词出现的所有次数,而不管其大小写格式如何。 编写一个程序,它读取你在项目Gutenberg中获取的文件,并计算单词'the'在每个文件中分别出现了多少次。 10.4 存储数据 很多程序都要求用户输入某种信息,如让用户存储游戏首选项或提供要可视化的数据。

w写入(打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。) r只读(以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。) a+追加(打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。)

 写入

这是一种在程序之间共享数据的简单方式。 10.4.2 保存和读取用户生成的数据 对于用户生成的数据,使用json保存它们大有裨益,因为如果不以某种方式进行存储,等程序停止运行时用户的信息将丢失。下面来看一个这样的例子:用户首次运行程序时被提示输入自己的名字,这样再次运行程序时就记住他了。 我们先来存储用户的名字: remember_me.py import json username = input("What is your name? ") ❶ filename = 'username.json' with open(filename, 'w') as f_obj: json.dump(username, f_obj) ❷ print("We'll remember you when you come back, "+username+"!") ❸ 在❶处,我们提示输入用户名,并将其存储在一个变量中。接下来,我们调用json.dump(),并将用户名和一个文件对象传递给它,从而将用户名存储到文件中(见❷)。

10.4.3 重构 你经常会遇到这样的情况:代码能够正确地运行,但可做进一步的改进——将代码划分为一系列完成具体工作的函数。这样的过程被称为重构。重构让代码更清晰、更易于理解、更容易扩展。 要重构remember_me.py,可将其大部分逻辑放到一个或多个函数中。remember_me.py的重点是问候用户,因此我们将其所有代码都放到一个名为greet_user()的函数中: remember_me.py import json def greet_user(): """问候用户,并指出其名字""" ❶ filename = 'username.json' try: with open(filename) as f_obj: username = json.load(f_obj) except FileNotFoundError: username = input("What is your name? ") with open(filename, 'w') as f_obj: json.dump(username, f_obj)

,这个函数只负责获取存储的用户名(如果存储了的话),再在必要时调用get_new_username(),这个函数只负责获取并存储新用户的用户名。要编写出清晰而易于维护和扩展的代码,这种划分工作必不可少。 动手试一试 10-11 喜欢的数字:编写一个程序,提示用户输入他喜欢的数字,并使用json.dump()将这个数字存储到文件中。再编写一个程序,从文件中读取这个值,并打印消息“I know your favorite number! It's _____.”。 10-12 记住喜欢的数字:将练习10-11中的两个程序合而为一。如果存储了用户喜欢的数字,就向用户显示它,否则提示用户输入他喜欢的数字并将其存储到文件中。运行这个程序两次,看看它是否像预期的那样工作。 10-13 验证用户:最后一个remember_me.py版本假设用户要么已输入其用户名,要么是首次运行该程序。我们应修改这个程序,以应对这样的情形:当前和最后一次运行该程序的用户并非同一个人。

第11章 测试代码

在本章中,你将学习如何使用Python模块unittest中的工具来测试代码。

name_function.py def get_formatted_name(first, last): """Generate a neatly formatted full name.""" full_name = first+' '+last return full_name.title() 函数get_formatted_name()将名和姓合并成姓名,在名和姓之间加上一个空格,并将它们的首字母都大写,再返回结果。为核实get_formatted_name()

表11-1 unittest Module中的断言方法

unittest.main() 我们将这个方法命名为test_store_three_responses(),并像test_store_single_response()一样,在其中创建一个调查对象。我们定义了一个包含三个不同答案的列表(见❶),再对其中每个答案都调用store_response()。存储这些答案后,我们使用一个循环来确认每个答案都包含在my_survey.responses中(见❷)。 我们再次运行test_survey.py时,两个测试(针对单个答案的测试和针对三个答案的测试)都通过了: .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK 前述做法的效果很好,但这些测试有些重复的地方。下面使用unittest的另一项功能来提高它们的效率。

z.py class Employee(): '''编写雇员类''' def __init__(self,name,xing,salary): self.name = name self.xing = xing self.salary = salary def give_raise(self,a=5000): self.salary += a ceshi.py import unittest from z import Employee class TestEmployee(unittest.TestCase): '''针对雇员类的测试''' def setUp(self): '''创建新的雇员实例,避免重复创建''' self.employee = Employee('rhz','jay',50000) def test_give_default_raise(self): '''工资默认增长''' a = self.employee.salary#获取当前工资值 self.employee.give_raise() self.assertEqual(self.employee.salary,a+5000) def test_give_custom_raise(self): '''工资自定义增长''' a = self.employee.salary#获取当前工资值 self.employee.give_raise(10000)#工资加10000 self.assertEqual(self.employee.salary,a+10000) unittest.main()

 为Employee编写一个测试用例,其中包含两个测试方法:test_give_default_raise()和test_give_custom_raise()。

第12章 武装飞船

Pygame,这是一组功能强大而有趣的模块,可用于管理图形、动画乃至声音,让你能够更轻松地开发复杂的游戏。

在游戏《外星人入侵》中,玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船,还可使用空格键进行射击。游戏开始时,一群外星人出现在天空中,他们在屏幕中向下移动。玩家的任务是射杀这些外星人。玩家将所有外星人都消灭干净后,将出现一群新的外星人,他们移动的速度更快。只要有外星人撞到了玩家的飞船或到达了屏幕底部,玩家就损失一艘飞船。玩家损失三艘飞船后,游戏结束。

如果你使用的是Linux系统和Python 2.7,或者是Windows,就无需使用pip来安装Pygame;在这种情况下,请直接跳到12.2.2节或12.2.4节。

12.2.4 在Windows系统中安装Pygame

余辉效应可以了解下

 使得只有新屏幕可见。在我们移动游戏元素时,pygame.display.flip()将不断更新屏幕,以显示元素的新位置,并在原来的位置隐藏元素,从而营造平滑移动的效果。

为了在屏幕上绘制玩家的飞船,我们将加载一幅图像,再使用Pygame方法blit()绘制它。

处理rect对象时,可使用矩形四角和中心的x和y坐标。可通过设置这些值来指定矩形的位置。

注意 在Pygame中,原点(0, 0)位于屏幕左上角,向右下方移动时,坐标值将增大。在1200×800的屏幕上,原点位于左上角,而右下角的坐标为(1200, 800)。

重构旨在简化既有代码的结构,使其更容易扩展。

game_functions

事件管理与游戏的其他方面(如更新屏幕

# 开始游戏主循环 while True: gf.check_events() gf.update_screen(ai_settings, screen, ship) run_game() 这两个函数让while循环更简单,并让后续开发更容易:在模块game_functions而不是run_game()中完成大部分工作。 鉴于我们一开始只想使用一个文件,因此没有立刻引入模块game_functions。这让你能够了解实际的开发过程:一开始将代码编写得尽可能简单,并在项目越来越复杂时进行重构。 对代码进行重构使其更容易扩展后,可以开始处理游戏的动态方面了! 动手试一试 12-1 蓝色天空:创建一个背景为蓝色的Pygame窗口。 12-2 游戏角色:找一幅你喜欢的游戏角色位图图像或将一幅图像转换为位图。创建一个类,将该角色绘制到屏幕中央,并将该图像的背景色设置为屏幕背景色,或将屏幕背景色设置为该图像的背景色。

鉴于我们一开始只想使用一个文件,因此没有立刻引入模块game_functions。这让你能够了解实际的开发过程:一开始将代码编写得尽可能简单,并在项目越来越复杂时进行重构。

实际的开发过程:一开始将代码编写得尽可能简单,并在项目越来越复杂时进行重构。

动手试一试 12-1 蓝色天空:创建一个背景为蓝色的Pygame窗口。 12-2 游戏角色:找一幅你喜欢的游戏角色位图图像或将一幅图像转换为位图。创建一个类,将该角色绘制到屏幕中央,并将该图像的背景色设置为屏幕背景色,或将屏幕背景色设置为该图像的背景色。 12.6 驾驶飞船

12-1 蓝色天空:创建一个背景为蓝色的Pygame窗口。

每当用户按键时,都将在Pygame中注册一个事件。事件都是通过方法pygame.event.get()获取的

第17章 使用API

GitHub(https://github.com/)的名字源自Git,Git是一个分布式版本控制系统,让程序员团队能够协作开发项目。

Unix时间或新纪元时间(1970年1月1日午夜后多少秒)

my_config = pygal.Config() ❶
my_config.x_label_rotation = 45 ❷
my_config.show_legend = False
my_config.title_font_size = 24 ❸
my_config.label_font_size = 14
my_config.major_label_font_size = 18
my_config.truncate_label = 15 ❹
my_config.show_y_guides = False ❺
my_config.width = 1000 ❻
chart = pygal.Bar(my_config, style=my_style) ❼
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
chart.add('', stars)
chart.render_to_file('python_repos.svg')​​ 在❶处,我们创建了一个Pygal类Config的实例,并将其命名为my_config。通过修改my_config的属性,可定制图表的外观。在❷处,我们设置了两个属性——x_label_rotation和show_legend,它们原来是在创建Bar实例时以关键字实参的方式传递的。在❸处,我们设置了图表标题、副标签和主标签的字体大小。在这个图表中,副标签是x轴上的项目名以及y轴上的大部分数字。主标签是y轴上为5000整数倍的刻度;这些标签应更大,以与副标签区分开来。在❹处,我们使用truncate_label将较长的项目名缩短为15个字符(如果你将鼠标指向屏幕上被截短的项目名,将显示完整的项目名)。接下来,我们将show_y_guides设置为False,以隐藏图表中的水平线(见❺)。最后,在❻处设置了自定义宽度,让图表更充分地利用浏览器中的可用空间。

第18章 Django入门

完整的规范详细说明了项目的目标,阐述了项目的功能,并讨论了项目的外观和用户界面。与任何良好的项目规划和商业计划书一样,规范应突出重点,帮助避免项目偏离轨道。

命令行窗口内执行cd /目录名可以进入对应目录,然后在对应目录下执行命令即可

 为项目新建一个目录,将其命名为learning_log,再在终端中切换到这个目录,并创建一个虚拟环境。

这里运行了模块venv,并使用它来创建一个名为ll_env的虚拟环境。

$pip install --user virtualenv​​ 别忘了,对于这个命令,你可能需要使用稍微不同的版本(如果你没有使用过pip,请参阅12.2.1节)。 
 注意 如果你使用的是Linux系统,且上面的做法不管用,可使用系统的包管理器来安装virtualenv。例如,要在Ubuntu系统中安装virtualenv,可使用命令sudo apt-get install python-virtualenv。 
 在终端中切换到目录learning_log,并像下面这样创建一个虚拟环境: ​​learning_log$virtualenv ll_env​​New python executable in ll_env/bin/python
Installing setuptools, pip...done.
learning_log$

如果你使用的是Windows系统,请使用命令ll_env\Scripts\activate(不包含source)来激活这个虚拟环境。 
 要停止使用虚拟环境,可执行命令deactivate:

Django仅在虚拟环境处于活动状态时才可用

18.1.6 在Django中创建项目 在依然处于活动的虚拟环境的情况下(ll_env包含在括号内),执行如下命令来新建一个项目: ​​(ll_env)learning_log$django-admin startproject learning_log . ❶
(ll_env)learning_log$ls ❷
learning_log ll_env manage.py
(ll_env)learning_log$ls learning_log ❸
__init__.py settings.py urls.py wsgi.py​​ ❶处的命令让Django新建一个名为learning_log的项目。这个命令末尾的句点让新项目使用合适的目录结构,这样开发完成后可轻松地将应用程序部署到服务器。 
 注意 千万别忘了这个句点,否则部署应用程序时将遭遇一些配置问题。如果忘记了这个句点,就将创建的文件和文件夹删除(ll_env除外),再重新运行这个命令。 
 在❸处,运行了命令ls(在Windows系统上应为dir),结果表明Django新建了一个名为learning_log的目录。它还创建了一个名为manage.py的文件,这是一个简单的程序,它接受命令并将其交给Django的相关部分去运行。我们将使用这些命令来管理诸如使用数据库和运行服务器等任务。 目录learning_log包含4个文件(见❸),其中最重要的是settings.py、urls.py和wsgi.py。文件settings.py指定Django如何与你的系统交互以及如何管理项目。在开发项目的过程中,我们将修改其中一些设置,并添加一些设置。文件urls.py告诉Django应创建哪些网页来响应浏览器请求。文件wsgi.py帮助Django提供它创建的文件,这个文件名是web server gateway interface(Web服务器网关接口)的首字母缩写。

我们将修改数据库称为迁移数据库

SQLite是一种使用单个文件的数据库,是编写简单应用程序的理想选择,因为它让你不用太关注数据库管理的问题。

localhost是一种只处理当前系统发出的请求,而不允许其他任何人查看你正在开发的网页的服务器。

如果出现错误消息“That port is already in use”(指定端口已被占用),请执行命令python manage.py runserver 8001,让Diango使用另一个端口;如果这个端口也不可用,请不断执行上述命令,并逐渐增大其中的端口号,直到找到可用的端口。

属性date_added是一个DateTimeField——记录日期和时间的数据(见❷)。我们传递了实参auto_now_add=True,每当用户创建新主题时,这都让Django将这个属性自动设置成当前日期和时间。

注意 要获悉可在模型中使用的各种字段,请参阅Django Model Field Reference(Django模型字段参考),其网址为https://docs.djangoproject.com/en/1.8/ref/models/fields/。

要使用模型,必须让Django将应用程序包含到项目中。为此,打开settings.py(

这是一个元组,告诉Django项目是由哪些应用程序组成的

这里新建了一个名为My apps的片段

接下来,需要让Django修改数据库,使其能够存储与模型Topic相关的信息。

Django允许你创建具备所有权限的用户——超级用户。权限决定了用户可执行的操作

Django并不存储你输入的密码,而存储从该密码派生出来的一个字符串——散列值。

Django自动在管理网站中添加了一些模型,如User和Group,但对于我们创建的模型,必须手工进行注册。

这些代码导入我们要注册的模型Topic(见❶),再使用admin.site.register()(见❷)让Django通过管理网站管理我们的模型。

请确认你在终端窗口中运行着Django服务器。如果没有,请激活虚拟环境,并执行命令python manage.py runserver。

像Topic一样,Entry也继承了Django基类Model(见❶)。第一个属性topic是一个ForeignKey实例(见❷)。外键是一个数据库术语,它引用了数据库中的另一条记录;这些代码将每个条目关联到特定的主题。每个主题创建时,都给它分配了一个键(或ID)。

18.2.5 迁移模型Entry

由于我们添加了一个新模型,因此需要再次迁移数据库。你将慢慢地对这个过程了如指掌:修改models.py,执行命令python manage.py makemigrationsapp_name,再执行命令python manage.py migrate。

我们导入了模块learning_logs.models中的模型Topic(见❶),然后使用方法Topic.objects.all()来获取模型Topic的所有实例;它返回的是一个列表,称为查询集(queryset)。

为通过外键关系获取数据,可使用相关模型的小写名称、下划线和单词set

例如,假设你有模型Pizza和Topping,而Topping通过一个外键关联到Pizza;如果你有一个名为my_pizza的对象,表示一张比萨,就可使用代码my_pizza.topping_set.all()来获取这张比萨的所有配料。

动手试一试 18-2 简短的条目:当前,Django在管理网站或shell中显示Entry实例时,模型Entry的方法__str__()都在它的末尾加上省略号。请在方法__str__()中添加一条if语句,以便仅在条目长度超过50字符时才添加省略号。使用管理网站来添加一个长度少于50字符的条目,并核实显示它时没有省略号。 18-3 Django API:编写访问项目中的数据的代码时,你编写的是查询。请浏览有关如何查询数据的文档,其网址为https://docs.djangoproject.com/en/7.8/topics/db/queries/。其中大部分内容都是你不熟悉的,但等你自己开发项目时,这些内容会很有用。 18-4 比萨店:新建一个名为pizzeria的项目,并在其中添加一个名为pizzas的应用程序。定义一个名为Pizza的模型,它包含字段name,用于存储比萨名称,如Hawaiian和Meat Lovers。定义一个名为Topping的模型,它包含字段pizza和name,其中字段pizza是一个关联到Pizza的外键,而字段name用于存储配料,如pineapple、Canadian bacon和sausage。 向管理网站注册这两个模型,并使用管理网站输入一些比萨名和配料。使用shell来查看你输入的数据。 18.3 创建网页:学习笔记主页

18-2 简短的条目:当前,Django在管理网站或shell中显示Entry实例时,模型Entry的方法__str__()都在它的末尾加上省略号。请在方法__str__()中添加一条if语句,以便仅在条目长度超过50字符时才添加省略号。使用管理网站来添加一个长度少于50字符的条目,并核实显示它时没有省略号。

Django 3.0.8 需修改为: (namespace功能修改到learning_logs.urls中使用app_name来实现) from django.contrib import admin from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), path('',include('learning_logs.urls')), ] 函数 include() 允许引用其它 URLconfs。每当 Django 遇到 include() 时,它会截断与此项匹配的 URL 的部分,并将剩余的字符串发送到 URLconf 以供进一步处理。 当包括其它 URL 模式时你应该总是使用 include() , admin.site.urls 是唯一例外。

 使用Django创建网页的过程通常分三个阶段:定义URL、编写视图和编写模板。首先,你必须定义URL模式。URL模式描述了URL是如何设计的,让Django知道如何将浏览器请求与网站URL匹配,以确定返回哪个网页。 每个URL都被映射到特定的视图——视图函数获取并处理网页所需的数据。视图函数通常调用一个模板,后者生成浏览器能够理解的网页。为明白其中的工作原理,我们来创建学习笔记的主页。我们将定义该主页的URL、编写其视图函数并创建一个简单的模板。 鉴于我们只是要确保“学习笔记”按要求的那样工作,我们将暂时让这个网页尽可能简单。Web应用程序能够正常运行后,设置样式可使其更有趣,但中看不中用的应用程序毫无意义。就目前而言,主页只显示标题和简单的描述。 18.3.1 映射URL 用户通过在浏览器中输入URL以及单击链接来请求网页,因此我们需要确定项目需要哪些URL。主页的URL最重要,它是用户用来访问项目的基础URL。当前,基础URL(http://localhost:8000/)返回默认的Django网站,让我们知道正确地建立了项目。我们将修改这一点,将这个基础URL映射到“学习笔记”的主页。 打开项目主文件夹learning_log中的文件urls.py,你将看到如下代码: urls.py

默认的urls.py包含在文件夹learning_log中,现在我们需要在文件夹learning_logs中创建另一个urls.py文件: urls.py """定义learning_logs的URL模式""" ❶ from django.conf.urls import url❷

这里向函数render()提供了两个实参:原始请求对象以及一个可用于创建网页的模板。

点评

认为推荐

Python真是一门强大的语言,花了远不止47个小时学完这本书,但现在可以确定的是,我可以开始进阶Python了[耶]

认为推荐

微信读书

版权声明:
作者:RHZ
链接:https://www.rhzhz.cn/?p=334
来源:RHZ | 用文字记录工作和学习生活
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
海报
Python编程:从入门到实践-埃里克·马瑟斯
220个笔记 第2章 变量和简单数据类型 变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头 · 慎用小写字母l和大写字……
<<上一篇
下一篇>>