《Python编程:从入门到实践》 笔记(一)基础知识

 

目录

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

第03章 列表简介

第04章 操作列表

第05章 if语句

第06章 字典

第07章 用户输入和while循环

第08章 函数

第09章 类

第10章 文件和异常

第11章 测试代码


  • 如果你只求很简单的应用、如果你学过其他语言,那么看这一篇就已经可以做到使用Python 编程了。

 

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

1. 变量

  • 变量:我们添加了一个名为message 的变量 。每个变量都存储了一个值 :与变量相关联的信息。
    在程序中可随时修改变量的值,而Python将始终记录变量的最新值。
message = "Hello Python world!"
print(message)
message = "Hello Python Crash Course world!"
print(message)
  • 变量的命名和使用:

    ①变量名只能包含字母(最好用小写字母)、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头,例如,可将变量命名为message_1,但不能将其命名为1_message。

    ②变量名不能包含空格,但可使用下划线来分隔其中的单词。例如,变量名greeting_message可行,但变量名greeting message会引发错误。

    ③不要将Python关键字和函数名用作变量名,即不要使用Python保留用于特殊用途的单词,如print。

    ④变量名应既简短又具有描述性。例如,name比n好,student_name比s_n好,name_length比length_of_persons_name好。

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

 

2. 字符串

  • 字符串:就是一系列字符。在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。这种灵活性让你能够在字符串中包含引号和撇号:
'I told my friend, "Python is my favorite language!"'
"The language 'Python' is named after Monty Python, not the snake."
"One of Python's strengths is its diverse and supportive community."
  • 使用方法修改字符串的大小写:
name = "ada lovelace"
print(name.title())

#输出:Ada Lovelace
  • 方法title() 出现在这个变量的后面。方法 是Python可对数据执行的操作。
    在name.title() 中,name 后面的句点(. )让Python对变量name 执行方法title() 指定的操作。每个方法后面都跟着一对括号,这是因为方法通常需要额外的信息来完成其工作。这种信息是在括号内提供的。函数title() 不需要额外的信息,因此它后面的括号是空的。
name = "Ada Lovelace"
print(name.upper())
print(name.lower())

#输出:ADA LOVELACE
#     ada lovelace

 

  • 合并(拼接)字符串:
    Python使用加号(+ )来合并字符串。在这个示例中,我们使用+ 来合并first_name 、空格和last_name ,以得到完整的姓名,其结果如下:
first_name = "ada"
last_name = "lovelace"
full_name = first_name + " " + last_name
print(full_name)


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

#输出:Hello, Ada Lovelace!

 

  • python字符串中,同样可以用\t 和 \n等制表符。
  • 删除字符串末尾多余的空白:
    ① >>> favorite_language = 'python '
    ② >>> favorite_language
    'python '
    ③ >>> favorite_language.rstrip()
    'python'
    ④ >>> favorite_language
    'python '
    存储在变量favorite_language 中的字符串末尾包含多余的空白(见①)。你在终端会话中向Python询问这个变量的值时,可看到末尾的空格(见②)。对变
    量favorite_language 调用方法rstrip() 后(见③),这个多余的空格被删除了。然而,这种删除只是暂时的,接下来再次询问favorite_language 的值时,你会发
    现这个字符串与输入时一样,依然包含多余的空白(见④)。
    要永久删除这个字符串中的空白,必须将删除操作的结果存回到变量中:
    favorite_language = 'python '
    favorite_language = favorite_language.rstrip()
  • 你还可以剔除字符串开头的空白:可使用方法 lstrip()

 

3. 数字

①整数

  • 在Python中,可对整数执行加(+ )减(- )乘(* )除(/ )求模(%)运算:

>>> 2 + 3
5 >>> 3
-
2
1 >>> 2
*
3
6 >>> 3
/
2
1.5
  • Python使用两个乘号表示乘方运算
>>> 3 ** 2
9 
>>> 3 ** 3
27
>>> 10 ** 6
1000000
  • Python还支持运算次序,因此你可在同一个表达式中使用多种运算。你还可以使用括号来修改运算次序,让Python按你指定的次序执行运算,如下所示:
>>> 2 + 3*4
14
>>> (2 + 3) * 4
20
  • 空格不影响Python计算表达式的方式,它们的存在旨在让你阅读代码时,能迅速确定先执行哪些运算。

②浮点数

  • 从很大程度上说,使用浮点数时都无需考虑其行为。你只需输入要使用的数字,Python通常都会按你期望的方式处理它们。但需要注意的是,结果包含的小数位数可能是不确定的:
>>> 0.2 + 0.1
0.30000000000000004
>>> 3 * 0.1
0.30000000000000004
  • 错误的代码,因为:Python发现你使用了一个值为整数(int )的变量,但它不知道该如何解读这个值。Python知道,这个变量表示的可能是数值23,也可能是字符2和3。像上面这样在字符串中使用整数时,需要显式地指出你希望Python将这个整数用作字符串。
     
    age = 23
    message = "Happy " + age + "rd Birthday!"
    print(message)
    为此,可调用函数str() ,它让Python将非字符串值表示为字符串
    age = 23
    message = "Happy " + str(age) + "rd Birthday!"
    print(message)

     

4.注释

  • 在Python中,注释用井号(# )标识。井号后面的内容都会被Python解释器忽略。

 

第03章 列表简介

1. 列表

  • 列表让你能够在一个地方存储成组的信息,其中可以只包含几个元素,也可以包含数百万个元素。列表是新手可直接使用的最强大的Python功能之一,它融合了众多重要的编程概念。
  • 列表:由一系列按特定顺序排列的元素组成。你可以创建包含字母表中所有字母、数字0~9或所有家庭成员姓名的列表;也可以将任何东西加入列表中,其中的元素之间可以没有任何关系。

 

  • 在Python中,用方括号([] )来表示列表,并用逗号来分隔其中的元素:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)

#输出:
#['trek', 'cannondale', 'redline', 'specialized']
  • 访问列表元素,下面的代码从列表bicycles 中提取第一款自行车(你还可以对任何列表元素调用第2章介绍的字符串方法):
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0])

#输出:trek
  • Python为访问最后一个列表元素提供了一种特殊语法。通过将索引指定为-1 ,可让Python返回最后一个列表元素:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[-1])

#输出:specialized

2. 修改、添加和删除元素

  • 修改元素
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles[0] = 'ducati'
print(motorcycles)
  • 给列表附加元素时,它将添加到列表末尾。继续使用前一个示例中的列表,在其末尾添加新元素'ducati' :
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.append('ducati')
print(motorcycles)

#输出:
#['honda', 'yamaha', 'suzuki']
#['honda', 'yamaha', 'suzuki', 'ducati']
  • 你可以先创建一个空列表,再使用一系列的append() 语句添加元素。
motorcycles = []
motorcycles.append('honda')
motorcycles.append('yamaha')
motorcycles.append('suzuki')
print(motorcycles)
  • 使用方法insert() 可在列表的任何位置添加新元素。这种操作将插入位置及其后面的每个元素都右移一个位置:
motorcycles = ['honda', 'yamaha', 'suzuki']
motorcycles.insert(0, 'ducati')
print(motorcycles)
  • 如果知道要删除的元素在列表中的位置,可使用del 语句:
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
del motorcycles[1]
print(motorcycles)
  • 方法pop() 可删除列表末尾的元素,并让你能够接着使用它:
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
popped_motorcycle = motorcycles.pop()
print(motorcycles)
print(popped_motorcycle)


#输出:
#['honda', 'yamaha', 'suzuki']
#['honda', 'yamaha']
#suzuki
  • 实际上,你可以使用pop() 来删除列表中任何位置的元素,只需在括号中指定要删除的元素的索引即可:
motorcycles = ['honda', 'yamaha', 'suzuki']
first_owned = motorcycles.pop(0)
print('The first motorcycle I owned was a ' + first_owned.title() + '.')
  • 有时候,你不知道要从列表中删除的值所处的位置。如果你只知道要删除的元素的值,可使用方法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.")

3. 组织列表

  • Python方法sort() 让你能够较为轻松地对列表进行排序:
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort()
print(cars)


#输出:
#['audi', 'bmw', 'subaru', 'toyota']
  • 你还可以按与字母顺序相反的顺序排列列表元素,为此,只需向sort() 方法传递参数reverse=True:
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort(reverse=True)
print(cars)
  • 要保留列表元素原来的排列顺序,同时以特定的顺序呈现它们,可使用函数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)
  • 要反转列表元素的排列顺序,可使用方法reverse() :
cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars)
cars.reverse()
print(cars)
  • 使用函数len() 可快速获悉列表的长度:
cars = ['bmw', 'audi', 'toyota', 'subaru']
print(len(cars))

 

第04章 操作列表

1. 遍历整个列表

  • for循环遍历:
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
    print(magician)
  • 在for 循环中,想包含多少行代码都可以。在代码行for magician in magicians 后面,每个缩进的代码行都是循环的一部分,且将针对列表中的每个值都执行一次。因此,可对列表中的每个值执行任意次数的操作:
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")
  • for 语句末尾的冒号告诉Python,下一行是循环的第一行。如果你不小心遗漏了冒号,将导致语法错误,因为Python不知道你意欲何为。

2.创建数值列表

  • Python函数range() 让你能够轻松地生成一系列的数字。range() 只是打印数字1~4,这是你在编程语言中经常看到的差一行为的结果。函数range() 让Python从你指定的第一个值开始数,并在到达你指定的第二个值后停止,因此输出不包含第二个值(这里为5):
for value in range(1,5):
    print(value)


#输出:
#1
#2
#3
#4
  • 要创建数字列表,可使用函数list() 将range() 的结果直接转换为列表。如果将range() 作为list() 的参数,输出将为一个数字列表:
numbers = list(range(1,6))
print(numbers)
  • 使用函数range() 时,还可指定步长。例如,下面的代码打印1~10内的偶数:
even_numbers = list(range(2,11,2))
print(even_numbers)
  • 使用函数range() 几乎能够创建任何需要的数字集,例如,如何创建一个列表,其中包含前10个整数(即1~10)的平方呢?在Python中,两个星号(** )表示乘方运算。下面的代码演示了如何将前10个整数的平方加入到一个列表中:
squares = []
for value in range(1,11):
    square = value**2
    squares.append(square)
print(squares)
  • 有几个专门用于处理数字列表的Python函数。例如,你可以轻松地找出数字列表的最大值、最小值和总和:
digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print(min(digits))
print(max(digits))
print(sum(digits))

 

  • 列表解析:将for 循环和创建新元素的代码合并成一行,并自动附加新元素。
  • 要使用这种语法,首先指定一个描述性的列表名,如squares ;然后,指定一个左方括号,并定义一个表达式,用于生成你要存储到列表中的值。
    在这个示例中,表达式为value**2 ,它计算平方值。接下来,编写一个for 循环,用于给表达式提供值,再加上右方括号。在这个示例中,for 循环为for value in range(1,11) ,它将值1~10提供给表达式value**2 。请注意,这里的for 语句末尾没有冒号。
squares = [value**2 for value in range(1,11)]
print(squares)

3. 使用列表的一部分

  • 你可以处理列表的部分元素——Python称之为切片
  • 要创建切片,可指定要使用的第一个元素和最后一个元素的索引。与函数range() 一样,Python在到达你指定的第二个索引前面的元素后停止。要输出列表中的前三个元素,需要指定索引0~3,这将输出分别为0 、1 和2 的元素:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3])

#输出:['charles', 'martina', 'michael']
  • 如果你没有指定第一个索引,Python将自动从列表开头开始。要让切片终止于列表末尾,也可使用类似的语法。
#自动从头开始
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[:4])

#自动到尾部结束
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[2:])
  • 负数索引返回离列表末尾相应距离的元素,因此你可以输出列表末尾的任何切片。
    例如,如果你要输出名单上的最后三名队员,可使用切片players[-3:] :
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[-3:])

 

  • 如果要遍历列表的部分元素,可在for 循环中使用切片:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print("Here are the first three players on my team:")
for player in players[:3]:
    print(player.title())
  • 通过切片复制一个列表(会有两个列表):
my_foods = ['pizza', 'falafel', 'carrot cake']

#会有两个不同的列表存在
friend_foods = my_foods[:]
my_foods.append('cannoli')
friend_foods.append('ice cream')
  • 而下面这个例子将my_foods 赋给friend_foods ,而不是将my_foods 的副本存储到friend_foods 。这种语法实际上是让Python将新变量friend_foods 关联到包含在my_foods 中的列表,因此这两个变量都指向同一个列表
my_foods = ['pizza', 'falafel', 'carrot cake']

#这行不通
friend_foods = my_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')

4.元组

  • 有时候你需要创建一系列不可修改的元素,元组可以满足这种需求。Python将不能修改的值称为不可变的 ,而不可变的列表被称为元组
  • 元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其元素,就像访问列表元素一样。
dimensions = (200, 50)
print(dimensions[0])
print(dimensions[1])
  • 像列表一样,也可以使用for 循环来遍历元组中的所有值。
  • 虽然不能修改元组的元素,但可以给存储元组的变量赋值。因此,如果要修改前述矩形的尺寸,可重新定义整个元组:
dimensions = (200, 50)
print("Original dimensions:")
for dimension in dimensions:
    print(dimension)

dimensions = (400, 100)
print("\nModified dimensions:")
for dimension in dimensions:
    print(dimension)

5. 代码格式

  • Python改进提案 (Python Enhancement Proposal,PEP):PEP 8是最古老的PEP之一,它向Python程序员提供了代码格式设置指南。PEP 8的篇幅很长,但大都与复杂的编码结构相关。

 

  • PEP 8建议每级缩进都使用四个空格,这既可提高可读性,又留下了足够的多级缩进空间。
  • 你在编写代码时应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。在程序中混合使用制表符和空格可能导致极难解决的问题。

 

  • 很多Python程序员都建议每行不超过80字符。
  • PEP 8还建议注释的行长都不超过72字符,因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符。

 

第05章 if语句

1. 条件测试

  • 这个示例中的循环首先检查当前的汽车名是否是'bmw' 。如果是,就以全大写的方式打印它;否则就以首字母大写的方式打印:
cars = ['audi', 'bmw', 'subaru', 'toyota']
for car in cars:
    if car == 'bmw':
        print(car.upper())
    else:
        print(car.title())
  • 在Python中检查是否相等时区分大小写,例如,两个大小写不同的值会被视为不相等:
car = 'Audi'
car == 'audi' #False
  • 如果大小写无关紧要,而只想检查变量的值,可将变量的值转换为小写,再进行比较:
car = 'Audi'
car.lower() == 'audi'    #True
  • 要判断两个值是否不等,可结合使用惊叹号和等号(!= ),其中的惊叹号表示不 ,在很多编程语言中都如此。
  • python中可以使用==、<、>、<=、>=来进行数值比较。
  • PEP 8提供的建议是,在诸如== 、>= 和<= 等比较运算符两边各添加一个空格。

 

  • 可以用and和or来检查多个条件:
age_0 = 22
age_1 = 18
age_0 >= 21 and age_1 >= 21 #False
age_0 = 22
age_1 = 18
age_0 >= 21 or age_1 >= 21 #True

 

  • 还有些时候,确定特定的值未包含在列表中很重要;在这种情况下,可使用关键字not in 。例如,如果有一个列表,其中包含被禁止在论坛上发表评论的用户,就可在允许用户提交评论前检查他是否被禁言:
banned_users = ['andrew', 'carolina', 'david']
user = 'marie'
if user not in banned_users:
    print(user.title() + ", you can post a response if you wish.")
  • 布尔表达式
game_active = True
can_edit = False

2. if语句

  • 最简单的if 语句只有一个测试和一个操作。在紧跟在if 语句后面的代码块中,可根据需要包含任意数量的代码行。
if conditional_test:
    do something
  • 经常需要在条件测试通过了时执行一个操作,并在没有通过时执行另一个操作;在这种情况下,可使用Python提供的if-else 语句。
age = 17

if age >= 18:
    print("You are old enough to vote!")
    print("Have you registered to vote yet?")
else:
    print("Sorry, you are too young to vote.")
    print("Please register to vote as soon as you turn 18!")
  • 经常需要检查超过两个的情形,为此可使用Python提供的if-elif-else 结构。Python只执行if-elif-else 结构中的一个代码块。
age = 12

if age < 4:
    print("Your admission cost is $0.")
elif age < 18:
    print("Your admission cost is $5.")
else:
    print("Your admission cost is $10.")

 

  • 可根据需要使用任意数量的elif 代码块。
  • Python并不要求if-elif 结构后面必须有else 代码块。

 

3. 使用if语句处理列表

  • 通过结合使用if 语句和列表,可完成一些有趣的任务:对列表中特定的值做特殊处理;高效地管理不断变化的情形,如餐馆是否还有特定的食材;证明代码在各种情形下都将按预期那样运行。

 

  • 比萨店在制作比萨时,每添加一种配料都打印一条消息。通过创建一个列表,在其中包含顾客点的配料,并使用一个循环来指出添加到比萨中的配料。然而,如果比萨店的青椒用完了,该如何处理呢?为妥善地处理这种情况,可在for 循环中包含一条if 语句:
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']

for requested_topping in requested_toppings:
    if requested_topping == 'green peppers':
        print("Sorry, we are out of green peppers right now.")
    else:
        print("Adding " + requested_topping + ".")

print("\nFinished making your pizza!")

 

  • 预先确定列表不是空的
requested_toppings = []
if requested_toppings:
    for requested_topping in requested_toppings:
        print("Adding " + requested_topping + ".")
    print("\nFinished making your pizza!")
else:
    print("Are you sure you want a plain pizza?")
  • 使用多个列表
available_toppings = ['mushrooms', 'olives', 'green peppers',
                      'pepperoni', 'pineapple', 'extra cheese']
requested_toppings = ['mushrooms', 'french fries', 'extra cheese']

for requested_topping in requested_toppings:
    if requested_topping in available_toppings:
        print("Adding " + requested_topping + ".")
    else:
        print("Sorry, we don't have " + requested_topping + ".")
print("\nFinished making your pizza!")

 

第06章 字典

1. 使用字典

  • 在Python中,字典:是一系列 键 - 值对 。每个键都与一个值相关联,你可以使用键来访问与之相关联的值。
  • 键 - 值对:两个相关联的值。指定键时,Python将返回与之相关联的值。
  • 值:可以是数字、字符串、列表乃至字典。事实上,可将任何Python对象用作字典中的值。
  • 在Python中,字典用放在花括号{} 中的一系列 键 - 值对 表示。键和值之间用冒号分隔,而键 - 值对之间用逗号分隔。
  • 在字典中,你想存储多少个键—值对都可以。最简单的字典只有一个键—值对

 

  • 要获取与键相关联的值,可依次指定字典名和放在方括号内的键。
alien_0 = {'color': 'green', 'points': 5}
print(alien_0['color'])
print(alien_0['points'])

#输出:
#green
#5
  • 要添加键—值对,可依次指定字典名、用方括号括起的键和相关联的值。
alien_0 = {'color': 'green', 'points': 5}

print(alien_0)
alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)


#输出:
#{'color': 'green', 'points': 5}
#{'color': 'green', 'points': 5, 'y_position': 25, 'x_position': 0}
  • 要修改字典中的值,可依次指定字典名、用方括号括起的键以及与该键相关联的新值。
alien_0 = {'color': 'green'}

alien_0['color'] = 'yellow'
  • 对于字典中不再需要的信息,可使用del 语句将相应的键-值对彻底删除。使用del 语句时,必须指定字典名和要删除的键。删除的键-值对永远消失了
alien_0 = {'color': 'green', 'points': 5}

del alien_0['points']

 

  • 你也可以使用字典来存储众多对象的同一种信息。我们将一个较大的字典放在了多行中。
  • 确定需要使用多行来定义字典时,在输入左花括号后按回车键,再在下一行缩进四个空格,指定第一个键-值对,并在它后面加上一个逗号。此后你再次按回车键时,文本编辑器将自动缩进后续键-值对,且缩进量与第一个键-值对相同。
  • 定义好字典后,在最后一个键-值对的下一行添加一个右花括号,并缩进四个空格,使其与字典中的键对齐。另外一种不错的做法是在最后一个键-值对后面也加上逗号,为以后在下一行添加键-值对做好准备。
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python',
    }

2. 遍历字典

  • 字典可用于以各种方式存储信息,因此有多种遍历字典的方式:可遍历字典的所有键—值对、键或值。
  • 要编写用于遍历字典的for 循环,可声明两个变量,用于存储键—值对中的键和值。对于这两个变量,可使用任何名称。for 语句的第二部分包含字典名和方法items() ,它返回一个键—值对列表。
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}

for key, value in user_0.items():
    print("\nKey: " + key)
    print("Value: " + value)
  • 即便遍历字典时,键-值对 的返回顺序也与存储顺序不同。Python不关心键—值对的存储顺序,而只跟踪键和值之间的关联关系。

 

  • 遍历字典中的所有键:在不需要使用字典中的值时,方法keys() 很有用。
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in favorite_languages.keys():
    print(name.title())
  • 遍历字典时,会默认遍历所有的键,因此,如果将上述代码中的for name in favorite_languages.keys(): 替换为for name in favorite_languages: ,输出将不变。
  • 按顺序遍历字典中的所有键,可使用函数sorted() 来获得按特定顺序排列的键列表的副本:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in sorted(favorite_languages.keys()):
    print(name.title() + ", thank you for taking the poll.")

 

  • 遍历字典中的所有值:如果你感兴趣的主要是字典包含的值,可使用方法values() ,它返回一个值列表,而不包含任何键。
  • 为剔除重复项,可使用集合(set)。集合:类似于列表,但每个元素都必须是独一无二的:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

print("The following languages have been mentioned:")
for language in set(favorite_languages.values()):
    print(language.title())

 

3.嵌套

  • 有时候,需要将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套 。你可以在列表中嵌套字典、在字典中嵌套列表甚至在字典中嵌套字典

 

  • 列表中嵌套字典
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)
# 创建一个用于存储外星人的空列表
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)))

 

  • 字典中嵌套列表
favorite_languages = {
    'jen': ['python', 'ruby'],
    'sarah': ['c'],
    'edward': ['ruby', 'go'],
    'phil': ['python', 'haskell'],
}

for name, languages in favorite_languages.items():
    print("\n" + name.title() + "'s favorite languages are:")

for language in languages:
    print("\t" + language.title())

 

  • 字典中嵌套字典:下面例子是有多个网站用户,每个都有独特的用户名,可在字典中将用户名作为键,然后将每位用户的信息存储在
    一个字典中,并将该字典作为与用户名相关联的值。在下面的程序中,对于每位用户,我们都存储了其三项信息:名、姓和居住地;为访问这些信息,我们遍历所有的用户名,并访问与每个用户名相关联的信息字典
users = {
    'aeinstein': {
        'first': 'albert',
        'last': 'einstein',
        'location': 'princeton',
        },
    'mcurie': {
        'first': 'marie',
        'last': 'curie',
        'location': 'paris',
        },
}

for username, user_info in users.items():
    print("\nUsername: " + username)
    full_name = user_info['first'] + " " + user_info['last']
    location = user_info['location']
    print("\tFull name: " + full_name.title())
    print("\tLocation: " + location.title())
  • 可在字典中嵌套字典,但这样做时,代码可能很快复杂起来。

 

第07章 用户输入和while循环

1. 函数input() 的工作原理

  • 函数input() 让程序暂停运行,等待用户输入一些文本。获取用户输入后,Python将其存储在一个变量中,以方便你使用。
message = input("Tell me something, and I will repeat it back to you: ")
print(message)
  • 使用函数input() 时,Python将用户输入解读为字符串。
age = input("How old are you? ")    #21
age

#输出:'21'
  • 可使用函数int() ,它让Python将输入转换为数值
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.")

2. while循环

  • 你可以使用while 循环来数数,例如,下面的while 循环从1数到5:
current_number = 1
while current_number <= 5:
    print(current_number)
    current_number += 1
  • 可使用while 循环让程序在用户愿意时不断地运行。我们在其中定义了一个退出值,只要用户输入的不是这个值,程序就接着运行:
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)

 

  • 要立即退出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() + "!")
  • 要返回到循环开头,并根据条件测试结果决定是否继续执行循环,可使用continue 语句,它不像break 语句那样不再执行余下的代码并退出整个循环。
current_number = 0

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

 

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

  • for 循环是一种遍历列表的有效方式,但在for 循环中不应修改列表,否则将导致Python难以跟踪其中的元素。要在遍历列表的同时对其进行修改,可使用while 循环。通过将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())
  • 可使用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 + ".")

 

第08章 函数

1. 定义函数

  • 使用关键字def 来告诉Python你要定义一个函数。这是函数定义 ,向Python指出了函数名,还可能在括号内指出函数为完成其任务需要什么样的信息。定义以冒号结尾。
  • 紧跟在def greet_user(): 后面的所有缩进行构成了函数体。三引号文本是被称为文档字符串 (docstring)的注释,描述了函数是做什么的。文档字符串用三引号括起,Python使用它们来生成有关程序中函数的文档。
def greet_user():
    """显示简单的问候语"""
    print("Hello!")

greet_user()
  • 向函数传递信息
def greet_user(username):
    """显示简单的问候语"""
    print("Hello, " + username.title() + "!")

greet_user('jesse')

2. 传递实参

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

 

  • 你调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参 。(和其他语言的函数调用类似)

 

  • 关键字实参:是传递给函数的 名称-值对。你直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆(不会得到名为Hamster的harry这样的结果)。关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。
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')

 

  • 编写函数时,可给每个形参指定默认值 。在调用函数中给形参提供了实参时,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')

#输出:
#I have a dog.
#My dog's name is Willie.
  • 由于给animal_type 指定了默认值,无需通过实参来指定动物类型,因此在函数调用中只包含一个实参——宠物的名字。然而,Python依然将这个实参视为位置实参,因此如果函数调用中只包含宠物的名字,这个实参将关联到函数定义中的第一个形参。这就是需要将pet_name 放在形参列表开头的原因所在。因此可以这样调用:describe_pet('willie')
  • 有时候,需要让实参变成可选的,这样使用函数的人就只需在必要时才提供额外的信息。可使用默认值来让实参变成可选的。

 

3. 返回值

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

 

  • 返回简单值:
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)
  • 返回字典:
def build_person(first_name, last_name):
    """返回一个字典,其中包含有关一个人的信息"""
    person = {'first': first_name, 'last': last_name}
    return person

musician = build_person('jimi', 'hendrix')
print(musician)

 

4. 传递列表

  • 你经常会发现,向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象(如字典)。将列表传递给函数后,函数就能直接访问其内容。下面使用函数来提高处理列表的效率。
  • 将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。
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)

 

  • 有时候,需要禁止函数修改列表。可向函数传递列表的副本而不是原件;这样函数所做的任何修改都只影响副本,而丝毫不影响原件: function_name(list_name[:])

 

5. 传递任意数量的实参

  • 有时候,你预先不知道函数需要接受多少个实参,好在Python允许函数从调用语句中收集任意数量的实参。
  • 形参名*toppings 中的星号让Python创建一个名为toppings 的空元组,并将收到的所有值都封装到这个元组中。注意,Python将实参封装到一个元组中,即便函数只收到一个值也如此。
  • 下面的函数只有一个形参*toppings ,但不管调用语句提供了多少实参,这个形参都将它们统统收入囊中:
def make_pizza(*toppings):
    """概述要制作的比萨"""
    print("\nMaking a pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)

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

#输出:
#Making a pizza with the following toppings:
#- pepperoni

#Making a pizza with the following toppings:
#- mushrooms
#- green peppers
#- extra cheese

 

  • 如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。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')

 

  • 使用任意数量的关键字实参:有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能够接受任意数量的 键-值对 ——调用语句提供了多少就接受多少。
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)

 

6. 将函数存储在模块中

  • 将函数存储在被称为模块 的独立文件中,再将模块导入 到主程序中。import 语句允许在当前运行的程序文件中使用模块中的代码。
  • 模块 是扩展名为.py的文件,包含要导入到程序中的代码。
  • 例子:
    ①我们将文件pizza.py中,除函数make_pizza() 之外的其他代码都删除。
    ②我们在pizza.py所在的目录中创建另一个名为making_pizzas.py的文件。
    ②在这个文件中用 import pizza 导入刚创建的模块,然后就可以在里面通过pizza.funname(),使用pizza.py中的函数了。

 

  • 你还可以导入模块中的特定函数,这种导入方法的语法如下:
    from module_name import function_0, function_1, function_2
    这种情况下,不用再用pizza.funname()调用,直接function_0()调用就好
  • 如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名 ——函数的另一个名称,类似于外号:from module_name import function_name as fn
  • 你还可以给模块指定别名。通过给模块指定简短的别名(如给模块pizza 指定别名p ),让你能够更轻松地调用模块中的函数:
    import module_name as mn

 

  • 使用星号(* )运算符可让Python导入模块中的所有函数:from module_name import *
  • 由于导入了每个函数,可通过名称来调用每个函数,而无需使用句点表示法。
  • 使用并非自己编写的大型模块时,最好不要采用这种导入方法:如果模块中有函数的名称与你的项目中使用的名称相同,可能导致意想不到的结果:Python可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入所有的函数。

 

第09章 类

1. 创建和使用类

  • 我们定义了一个名为Dog 的类。
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!")
  • 根据约定,在Python中,首字母大写的名称指的是类。
  • 类中的函数称为方法:你前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用方法的方式。
  • 方法__init__():这是一个特殊的方法,每当你根据Dog 类创建新实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
  • 我们将方法__init__() 定义成了包含三个形参:self 、name 和age 。

    在这个方法的定义中,形参self 必不可少,还必须位于其他形参的前面。为何必须在方法定义中包含形参self 呢?因为Python调用这个__init__() 方法来创建Dog 实例时,将自动传入实参self 。

    每个与类相关联的方法调用都自动传递实参self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
  • 我们创建Dog 实例时,Python将调用Dog 类的方法__init__() 。我们将通过实参向Dog() 传递名字和年龄;self 会自动传递,因此我们不需要传递它。每当我们根据Dog 类创建实例时,都只需给最后两个形参(name 和age )提供值。
  • Dog 类还定义了另外两个方法:sit() 和roll_over() 。由于这些方法不需要额外的信息,如名字或年龄,因此它们只有一个形参self。

 

  • 创建一个类的实例(对象):
my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")

 

2. 使用类和实例

  • 类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。
  • 在有些情况下,如设置默认值时,在方法__init__() 内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
class Car():
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
    def get_descriptive_name(self):
        """返回整洁的描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")

#使用类
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

 

  • 可以以三种不同的方式修改属性的值:直接通过实例进行修改通过方法进行设置通过方法进行递增(增加特定的值)。

 

3.继承

  • 一个类继承 另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类 ,而新类称为子类
  • 子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

 

  • 创建子类时,父类必须包含在当前文件中,且位于子类前面。
  • super() 是一个特殊函数,帮助Python将父类和子类关联起来。通过super调用父类中的属性和方法。
  • 让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
  • 对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。
  • 我们还可以将另一个类的实例用作类的属性。

 

  • 例子:电动汽车是一种特殊的汽车,因此我们可以在前面创建的Car 类的基础上创建新类ElectricCar ,这样我们就只需为电动汽车特有的属性和行为编写代码。
#父类:Car
class Car():
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
    def read_odometer(self):
        print("This car has " + str(self.odometer_reading) + " miles on it.")
    def update_odometer(self, mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
    def increment_odometer(self, miles):
        self.odometer_reading += miles

#另一个类:Battery
class Battery():
    """一次模拟电动汽车电瓶的简单尝试"""
    def __init__(self, battery_size=70):
        """初始化电瓶的属性"""
        self.battery_size = battery_size
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
    def get_range(self):
        """打印一条消息,指出电瓶的续航里程"""
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270
        message = "This car can go approximately " + str(range)
        message += " miles on a full charge."
        print(message)

#子类:ElectricCar
class ElectricCar(Car):
    """电动汽车的独特之处"""
    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()
my_tesla.battery.get_range()

 

4. 导入类

  • 和函数的操作类似。
  • 可根据需要在程序文件中导入任意数量的类。from car import Car, ElectricCar
  • 有时候,需要将类分散到多个模块中,以免模块太大,或在同一个模块中存储不相关的类。将类存储在多个模块中时,你可能会发现一个模块中的类依赖于另一个模块中的类。在这种情况下,可在前一个模块中导入必要的类。

5. Python标准库

  • Python标准库 是一组模块,安装的Python都包含它。

 

  • 字典让你能够将信息关联起来,但它们不记录你添加键-值对的顺序。要创建字典并记录其中的键-值对的添加顺序,可使用模块collections 中的OrderedDict类。OrderedDict 实例的行为几乎与字典相同,区别只在于记录了键-值对的添加顺序。
from collections import OrderedDict

favorite_languages = OrderedDict()
favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'

for name, language in favorite_languages.items():
    print(name.title() + "'s favorite language is " +
        language.title() + ".")
  • 类名应采用驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
  • 对于每个类,都应紧跟在类定义后面包含一个文档字符串。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
  • 在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
  • 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import 语句,再添加一个空行,然后编写导入你自己编写的模块的import 语句。

 

第10章 文件和异常

1. 从文件中读取数据

  • 要以任何方式使用文件——哪怕仅仅是打印其内容,都得先打开 文件,这样才能访问它。函数open()接受一个参数:要打开的文件的名称。Python在当前执行的文件所在的目录中查找指定的文件。函数open() 返回一个表示文件的对象。
  • 关键字with 在不再需要访问文件后将其关闭(隐式地调用close()函数)。使用关键字with 时,open() 返回的文件对象只在with 代码块内可用。
  • 你也可以调用open() 和close() 来打开和关闭文件,但这样做时,如果程序存在bug,导致close() 语句未执行,文件将不会关闭。
  • 有了表示文件的对象后,我们使用方法read() 来读取这个文件的全部内容。
  • read() 到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删除多出来的空行,可在print 语句中使用rstrip() 。
with open('pi_digits.txt') as file_object:
    contents = file_object.read()
    print(contents)
  • 有时候文件不在程序目录下,可写出完整路径去寻找:
file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:
  • 要以每次一行的方式检查文件,可对文件对象使用for 循环。
filename = 'pi_digits.txt'
with open(filename) as file_object:
    for line in file_object:
    print(line)

 

  • 可在with 代码块内将文件的各行存储在一个列表中,并在with 代码块外使用该列表:这样你可以立即处理文件的各个部分,也可推迟到程序后面再处理。
  • 方法readlines() 从文件中读取每一行,并将其存储在一个列表中。
filename = 'pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()

for line in lines:
    print(line.rstrip())

 

2. 写入文件

  • 要将文本写入文件,你在调用open() 时需要提供另一个实参'w',告诉Python你要写入打开的文件。
  • 调用open() 时提供了两个实参。第一个实参也是要打开的文件的名称;第二个实参('w' )告诉Python,我们要以写入模式 打开这个文件。
  • 打开文件时,可指定读取模式 ('r' )、写入模式 ('w' )、附加模式 ('a' )或让你能够读取和写入文件的模式('r+' )。如果你省略了模式实参,Python将以默认的只读模式打开文件。
  • 如果你要写入的文件不存在,函数open() 将自动创建它。然而,以写入('w' )模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。
  • 如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式 打开文件。
  • Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str() 将其转换为字符串格式。
filename = 'programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.")

 

3. 异常

  • Python使用被称为异常特殊对象来管理程序执行期间发生的错误。
  • 发生错误时,如果你编写了处理该异常的代码,程序将继续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。
  • 当你认为可能发生了错误时,可编写一个try-except 代码块来处理可能引发的异常。你让Python尝试运行一些代码,并告诉它如果这些代码引发了指定的异常,该怎么办。
try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

4. 存储数据

  • 模块json 让你能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。
  • 你还可以使用json 在Python程序之间分享数据。更重要的是,JSON数据格式并非Python专用的,这让你能够将以JSON格式存储的数据与使用其他编程语言的人分享。这是一种轻便格式,很有用,也易于学习。
    JSON(JavaScript Object Notation)格式最初是为JavaScript开发的,但随后成了一种常见格式,被包括Python在内的众多语言采用。

 

  • 函数json.dump() 接受两个实参:要存储的数据以及可用于存储数据的文件对象。
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'

with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)
  • 再使用函数json.load() 加载存储在numbers.json中的信息,并将其存储到变量numbers 中。
import json
filename = 'numbers.json'
with open(filename) as f_obj:
   numbers = json.load(f_obj)
print(numbers)

 

第11章 测试代码

1. 测试函数

  • 下面是一段手动测试函数的代码
def get_formatted_name(first, last):
    """Generate a neatly formatted full name."""
    full_name = first + ' ' + last
    return full_name.title()
    
print("Enter 'q' at any time to quit.")
while True:
    first = input("\nPlease give me a first name: ")
    if first == 'q':
        break
    last = input("Please give me a last name: ")
    if last == 'q':
        break
    formatted_name = get_formatted_name(first, last)
    print("\tNeatly formatted name: " + formatted_name + '.')

 

  • Python中有模块unittest,专门用于测试。
  • 下面是一个只包含一个方法的测试用例,它检查函数get_formatted_name() 在给定名和姓时能否正确地工作。(通常测试文件和函数文件最好是两个文件,这里为了方便看放一起了)
import unittest

def get_formatted_name(first, last):
    """Generate a neatly formatted full name."""
    full_name = first + ' ' + last
    return full_name.title()
    
class NamesTestCase(unittest.TestCase):
    """测试name_function.py"""
    def test_first_last_name(self):
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')
    
unittest.main()
  • 我们创建了一个名为NamesTestCase 的类,用于包含一系列针对get_formatted_name() 的单元测试。你可随便给这个类命名,但最好让它看起来与要测试的函数相关,并包含字样Test。这个类必须继承unittest.TestCase 类,这样Python才知道如何运行你编写的测试。
  • NamesTestCase 只包含一个方法,用于测试get_formatted_name() 的一个方面。我们将这个方法命名为test_first_last_name() ,因为我们要核实的是只有名和姓的姓名能否被正确地格式化。
  • 我们运行时,所有以test 打头的方法都将自动运行。在这个方法中,我们调用了要测试的函数,并存储了要测试的返回值。在这个示例中,我们使用实参'janis' 和'joplin' 调用get_formatted_name() ,并将结果存储到变量formatted_name 中。
  • 在这里,我们知道get_formatted_name() 应返回这样的姓名,即名和姓的首字母为大写,且它们之间有一个空格,因此我们期望formatted_name 的值为Janis Joplin 。为检查是否确实如此,我们调用unittest的方法assertEqual() ,并向它传递formatted_name 和'Janis Joplin' 。代码行self.assertEqual(formatted_name, 'Janis Joplin') 的意思是说:“将formatted_name 的值同字符串'Janis Joplin' 进行比较,如果它们相等,就万事大吉,如果它们不相等,跟我说一声!”

2. 测试类

  • Python在unittest.TestCase 类中提供了很多断言方法。前面说过,断言方法检查你认为应该满足的条件是否确实满足。如果该条件确实满足,你对程序行为的假设就得到了确认,你就可以确信其中没有错误。如果你认为应该满足的条件实际上并不满足,Python将引发异常。

  • 我们首先导入了模块unittest 以及要测试的类AnonymousSurvey 。我们将测试用例命名为TestAnonymousSurvey ,它也继承了unittest.TestCase。第一个测试方法验证调查问题的单个答案被存储后,会包含在调查结果列表中。对于这个方法,一个不错的描述性名称是test_store_single_response() 。如果这个测试未通过,我们就能通过输出中的方法名得知,在存储单个调查答案方面存在问题。
    要测试类的行为,需要创建其实例。我们使用问题"What language did you first learn to speak?" 创建了一个名为my_survey 的实例,然后使用方法store_response() 存储了单个答案English 。接下来,我们检查English 是否包含在列表my_survey.responses 中,以核实这个答案是否被妥善地存储了
import unittest
from survey import AnonymousSurvey

class TestAnonmyousSurvey(unittest.TestCase):
    """针对AnonymousSurvey类的测试"""
    def test_store_single_response(self):
        """测试单个答案会被妥善地存储"""
        question = "What language did you first learn to speak?"
        my_survey = AnonymousSurvey(question)
        my_survey.store_response('English')
        self.assertIn('English', my_survey.responses)

unittest.main()
  • 61
    点赞
  • 314
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值