python从入门到实践-学习笔记

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

2.3 字符串

2.3.1 大小写转换

name="jeckson cool"
print(name.title()) #开头大写
print(name.lower()) #全小写
print(name.upper()) #全大写
Jeckson Cool
jeckson cool
JECKSON COOL

2.3.2 合并(拼接)字符串

first_name="jeckson"
last_name="yin"
full_name=first_name+"."+last_name #拼接 +
print(full_name)
jeckson.yin

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

print("j\te\tc\tk\ts\to\tn") #制表符
print("j\ne\nc\nk\ns\no\nn") #换行符
j	e	c	k	s	o	n
j
e
c
k
s
o
n

2.3.4 删除空白

str_strip="  jeckson  "
print(str_strip.lstrip()) #左边
print(str_strip.rstrip()) #右边
print(str_strip.strip())  #两边
jeckson  
  jeckson
jeckson
str_strip

2.4 数字

2.4.1 整数

a1=2+3
a2=2-3
a3=2*3
a4=2/3
a5=2**3
print(a1,a2,a3,a4,a5)
5 -1 6 0.6666666666666666 8

2.4.2 浮点数

a1=0.1+0.2
a2=1.2*2
print(a1,a2)
0.30000000000000004 2.4

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

age=18
message1="happy"+str(age)+"rd birthday"
print(message1)
happy18rd birthday

2.4.4 Python 2 中的整数

a1=3/2  #python2 中结果为 1,计算整数结果时,采取的方式不是四舍五入,而是将小数部分直接删除。
        #在Python 2中,若要避免这种情况,务必确保至少有一个操作数为浮点数,这样结果也将为浮点数
a2=3/2.0
print(a1,a2)
1.5 1.5

python之禅

import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

第3章 列表简介

3.1 列表

3.1.1 访问列表元素

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

3.1.2 索引从 0 而不是 1 开始

bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0],bicycles[1]) #0,1对应第1,2个
print(bicycles[-1],bicycles[-2]) #不知道多少个的情况、访问最后一个元素,类似的[-2]倒数第二个
trek cannondale
specialized redline

3.1.3 使用列表中的各个值

bicycles = ['trek', 'cannondale', 'redline', 'specialized']
message = "My first bicycle was a " + bicycles[0].title() + "."
print(message)
My first bicycle was a Trek.

3.2 修改、添加和删除元素

3.2.1 修改列表元素

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

3.2.2 在列表中添加元素

motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.append('ducati') #末尾追加一个
print(motorcycles)
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha', 'suzuki', 'ducati']
motorcycles = ['honda', 'yamaha', 'suzuki']
motorcycles.insert(1, 'ducati') #指定位置插入一个
print(motorcycles)
['honda', 'ducati', 'yamaha', 'suzuki']

3.2.3 从列表中删除元素

motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
del motorcycles[0] #删除指定元素
print(motorcycles)
['honda', 'yamaha', 'suzuki']
['yamaha', 'suzuki']
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
popped_motorcycle = motorcycles.pop() #弹出末尾元素、并且可以使用
print(motorcycles)
print(popped_motorcycle)
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha']
suzuki
motorcycles = ['honda', 'yamaha', 'suzuki']
first_owned = motorcycles.pop(0) #弹出指定位置元素
print(motorcycles)
print('The first motorcycle I owned was a ' + first_owned.title() + '.')
['yamaha', 'suzuki']
The first motorcycle I owned was a Honda.
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)
motorcycles.remove('ducati') #根据值来删除元素
print(motorcycles)
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']

3.3 组织列表

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

cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort() #按字母永久性排序
print(cars)
cars.sort(reverse=True) #按字母反向永久性排序
print(cars)
['audi', 'bmw', 'subaru', 'toyota']
['toyota', 'subaru', 'bmw', 'audi']

3.3.2 使用函数 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 倒着打印列表

cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars)
cars.reverse() #直接将列表反转,永久性,但可以恢复,秩序再来一次就好了
print(cars)
['bmw', 'audi', 'toyota', 'subaru']
['subaru', 'toyota', 'audi', 'bmw']

3.3.4 确定列表的长度

cars = ['bmw', 'audi', 'toyota', 'subaru']
print(len(cars)) #显示列表长度
4

3.4 使用列表时避免索引错误

避免使用时超过长度,可以使用.len()方法查询长度

第4章 操作列表

4.1 遍历整个列表

4.1.1 深入地研究循环

magicians = ['alice', 'david', 'carolina']
for magician in magicians:
    print(magician)
alice
david
carolina

4.1.2 在 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")
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.

4.1.3 在 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!") #将相应的代码放在for循环后面,且不缩进
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!

4.2 避免缩进错误

Python根据缩进来判断代码行与前一个代码行的关系。
你开始编写必须正确缩进的代码时,需要注意一些常见的缩进错误:

4.2.1 忘记缩进

magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)
  File "<ipython-input-5-bc3e0c643e2b>", line 3
    print(magician)
        ^
IndentationError: expected an indented block

4.2.2 忘记缩进额外的代码行

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") #从语法上看,这些Python代码是合法的,但由于存在逻辑错误,
#结果并不符合预期
Alice, that was a great trick!
David, that was a great trick!
Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

4.2.3 不必要的缩进

message = "Hello Python world!"
    print(message) #无需缩进,因为它并不属于前一行代码
  File "<ipython-input-7-e744c47c5d20>", line 2
    print(message)
    ^
IndentationError: unexpected indent

4.2.4 循环后不必要的缩进

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!") #这也是一个逻辑错误,与4.2.2节的错误类似。 Python不知道你的本意,
#只要代码符合语法,它就会运行
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

Thank you everyone, that was a great magic show!
David, that was a great trick!
I can't wait to see your next trick, David.

Thank you everyone, that was a great magic show!
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!

4.2.5 遗漏了冒号

magicians = ['alice', 'david', 'carolina']
for magician in magicians #for语句末尾的冒号告诉Python,下一行是循环的第一行
#如果你不小心遗漏了冒号,如所示,将导致语法错误,因为Python不知道你意欲何为。
    print(magician) 
  File "<ipython-input-9-37ef8fcabfe3>", line 2
    for magician in magicians #for语句末尾的冒号告诉Python,下一行是循环的第一行
                                                            ^
SyntaxError: invalid syntax

4.3 创建数值列表

4.3.1 使用函数 range()

for value in range(1,5):
    print(value) #函数range()让Python从你指定的第一个值开始数,并在到达你指定的第二个值后停止,因此输出
#不包含第二个值(这里为5)
1
2
3
4

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

numbers = list(range(1,6))
print(numbers) #打印了一系列数字,要将这些数字转换为一个列表,可使用list()
[1, 2, 3, 4, 5]
even_numbers = list(range(2,11,2))
print(even_numbers) #使用函数range()时,还可指定步长。例如,打印1~10内的偶数
#函数range()从2开始数,然后不断地加2,直到达到或超过终值( 11)
[2, 4, 6, 8, 10]
squares = []
for value in range(1,11):
    square = value**2
    squares.append(square)
print(squares) #将前10个整数的平方加入到一个列表中
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
squares = []
for value in range(1,11):
    squares.append(value**2)
print(squares)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

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

digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print(min(digits)) #最大值
print(max(digits)) #最小值
print(sum(digits)) #求和
0
9
45

4.3.4 列表解析

squares = [value**2 for value in range(1,11)]
print(squares)
# 要使用这种语法,首先指定一个描述性的列表名,如squares;然后,指定一个左方括号,
# 并定义一个表达式,用于生成你要存储到列表中的值。在这个示例中,表达式为value**2,它计
# 算平方值。接下来,编写一个for循环,用于给表达式提供值,再加上右方括号。在这个示例中,
# 图灵社区会员 江子涛Tesla(jiangzitao201314@foxmail.com) 专享 尊重版权54 第 4 章 操作列表
# for循环为for value in range(1,11),它将值1~10提供给表达式value**2。请注意,这里的for
# 语句末尾没有冒号。

# 列表解析编写更加精简,运行速度更快(快一倍)。
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
nbs=[nb**3 for nb in range(1,11) if nb%2==0]
print(nbs)
[8, 64, 216, 512, 1000]

4.4 使用列表的一部分

4.4.1 切片

players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3]) #与函数range()一样, Python在到达你指定的第二个索引前面的元素后停止。
['charles', 'martina', 'michael']
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[1:4])
['martina', 'michael', 'florence']
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[:4])#如果你没有指定第一个索引, Python将自动从列表开头开始
['charles', 'martina', 'michael', 'florence']
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[2:])#要让切片终止于列表末尾,也可使用类似的语法。
['michael', 'florence', 'eli']
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[-3:])#要输出名单上的最后三名队员
['michael', 'florence', 'eli']

4.4.2 遍历切片

players = ['charles', 'martina', 'michael', 'florence', 'eli']
print("Here are the first three players on my team:")
for player in players[:3]:
    print(player.title())
Here are the first three players on my team:
Charles
Martina
Michael

4.4.3 复制列表

my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)
My favorite foods are:
['pizza', 'falafel', 'carrot cake']

My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake']
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
my_foods.append('cannoli')
friend_foods.append('ice cream')
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)
My favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli']

My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake', 'ice cream']
my_foods = ['pizza', 'falafel', 'carrot cake']
#这行不通
friend_foods = my_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)
# 这里将my_foods赋给friend_foods,而不是将my_foods的副本存储到friend_foods(见)。
# 这种语法实际上是让Python将新变量friend_foods关联到包含在my_foods中的列表,因此这两个
# 变量都指向同一个列表。鉴于此,当我们将'cannoli'添加到my_foods中时,它也将出现在
# friend_foods中;同样,虽然'ice cream'好像只被加入到了friend_foods中,但它也将出现在这
# 两个列表中
My favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

4.5 元组

4.5.1 定义元组

列表非常适合用于存储在程序运行期间可能变化的数据集。列表是可以修改的,这对处理网
站的用户列表或游戏中的角色列表至关重要。然而,有时候你需要创建一系列不可修改的元素,
元组可以满足这种需求。 Python将不能修改的值称为不可变的,而不可变的列表被称为元组。

dimensions = (200, 50)
print(dimensions[0])
print(dimensions[1])
200
50
dimensions = (200, 50)
dimensions[0] = 250 #尝试修改元组
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-42-e8fc93a48ec2> in <module>
      1 dimensions = (200, 50)
----> 2 dimensions[0] = 250 #尝试修改元组


TypeError: 'tuple' object does not support item assignment

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 设置代码格式

4.6.1 格式设置指南

Python格式设置指南的编写者深知,代码被阅读的次数比编写的次数多。代码编写出来后,
调试时你需要阅读它;给程序添加新功能时,需要花很长的时间阅读代码;与其他程序员分享代
码时,这些程序员也将阅读它们。

4.6.2 缩进

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

4.6.3 行长

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

4.6.4 空行

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

4.6.5 其他格式设置指南

PEP 8指南

第5章 if语句

5.1 一个简单示例

cars = ['audi', 'bmw', 'subaru', 'toyota']
for car in cars:
    if car == 'bmw':
        print(car.upper())
    else:
        print(car.title())
Audi
BMW
Subaru
Toyota

5.2 条件测试

每条if语句的核心都是一个值为True或False的表达式,这种表达式被称为条件测试。

5.2.1 检查是否相等

car = 'bmw'#将car的值设置为'bmw'
print(car == 'bmw')#使用两个等号( ==)检查car的值是否为'bmw'
True

5.2.2 检查是否相等时不考虑大小写

car = 'Audi'
print(car == 'audi')
print(car.lower() == 'audi')
False
True

5.2.3 检查是否不相等

requested_topping = 'mushrooms'
if requested_topping != 'anchovies':
    print("Hold the anchovies!")
Hold the anchovies!

5.2.4 比较数字

age = 19
print(age < 21)
print(age <= 21)
print(age > 21)
print(age >= 21)
True
True
False
False

5.2.5 检查多个条件

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

age_1 = 22
print(age_0 >= 21 and age_1 >= 21)

False
True
  1. 使用or检查多个条件
    关键字or也能够让你检查多个条件,但只要至少有一个条件满足,就能通过整个测试。
    仅当两个测试都没有通过时,使用or的表达式才为False
age_0 = 22
age_1 = 18
print(age_0 >= 21 or age_1 >= 21)
age_0 = 18
print(age_0 >= 21 or age_1 >= 21)
True
False

5.2.6 检查特定值是否包含在列表中

requested_toppings = ['mushrooms', 'onions', 'pineapple']
print('mushrooms' in requested_toppings)

print('pepperoni' in requested_toppings)

True
False

5.2.7 检查特定值是否不包含在列表中

banned_users = ['andrew', 'carolina', 'david']
user = 'marie'
if user not in banned_users:
    print(user.title() + ", you can post a response if you wish.")
Marie, you can post a response if you wish.

5.2.8 布尔表达式

game_active = True
can_edit = False

5.3 if 语句

5.3.1 简单的 if 语句

age = 19
if age >= 18:
    print("You are old enough to vote!")
You are old enough to vote!

5.3.2 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!")
Sorry, you are too young to vote.
Please register to vote as soon as you turn 18!

5.3.3 if-elif-else 结构

age = 3
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.")
Your admission cost is $0.

5.3.4 使用多个 elif 代码块

age = 20
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) + ".")
Your admission cost is $10.

5.3.5 省略 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) + ".")
Your admission cost is $5.

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

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!")
Adding mushrooms.
Adding extra cheese.

Finished making your pizza!

5.4 使用 if 语句处理列表

5.4.1 检查特殊元素

requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings:
    print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
Adding mushrooms.
Adding green peppers.
Adding extra cheese.

Finished making your pizza!
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!")
Adding mushrooms.
Sorry, we are out of green peppers right now.
Adding extra cheese.

Finished making your pizza!

5.4.2 确定列表不是空的

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?")
Are you sure you want a plain pizza?

5.4.3 使用多个列表

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 + ".")
Adding mushrooms.
Sorry, we don't have french fries.
Adding extra cheese.

5.5 设置 if 语句的格式

本章的每个示例都展示了良好的格式设置习惯。在条件测试的格式设置方面, PEP 8提供的唯一
建议是,
在诸如==、 >=和<=等比较运算符两边各添加一个空格,
例如, if age < 4:要比if age<4:好。
这样的空格不会影响Python对代码的解读,而只是让代码阅读起来更容易。

第6章 字典

6.1 一个简单的字典

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

6.2 使用字典

6.2.1 访问字典中的值

alien_0 = {'color': 'green'}
print(alien_0['color'])
green
alien_0 = {'color': 'green', 'points': 5}
new_points = alien_0['points']
print("You just earned " + str(new_points) + " points!")
You just earned 5 points!

6.2.2 添加键—值对

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, 'x_position': 0, 'y_position': 25}

6.2.3 先创建一个空字典

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

6.2.4 修改字典中的值

alien_0 = {'color': 'green'}
print("The alien is " + alien_0['color'] + ".")
alien_0['color'] = 'yellow'
print("The alien is now " + alien_0['color'] + ".")
The alien is green.
The alien is now yellow.
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']))
Original x-position: 0
New x-position: 2

6.2.5 删除键— 值对

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

6.2.6 由类似对象组成的字典

favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

6.3 遍历字典

6.3.1 遍历所有的键— 值对

user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}
for key, value in user_0.items():
    print("\nKey: " + key)
    print("Value: " + value)
Key: username
Value: efermi

Key: first
Value: enrico

Key: last
Value: fermi

6.3.2 遍历字典中的所有键

favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in favorite_languages.keys():
    print(name.title())
Jen
Sarah
Edward
Phil
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
friends = ['phil', 'sarah']
for name in favorite_languages.keys():
    print(name.title())
    if name in friends:
        print(" Hi " + name.title() +", I see your favorite language is " +favorite_languages[name].title() + "!")
Jen
Sarah
 Hi Sarah, I see your favorite language is C!
Edward
Phil
 Hi Phil, I see your favorite language is Python!

6.3.3 按顺序遍历字典中的所有键

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.")
Edward, thank you for taking the poll.
Jen, thank you for taking the poll.
Phil, thank you for taking the poll.
Sarah, thank you for taking the poll.

6.3.4 遍历字典中的所有值

favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python'
    }
print("The following languages have been mentioned:")
for language in favorite_languages.values():
    print(language.title())
The following languages have been mentioned:
Python
C
Ruby
Python
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())
The following languages have been mentioned:
C
Python
Ruby

6.4 嵌套

6.4.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)
{'color': 'green', 'points': 5}
{'color': 'yellow', 'points': 10}
{'color': 'red', 'points': 15}
# 创建一个用于存储外星人的空列表
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)))
{'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, 'speed': 'slow'}
...
Total number of aliens: 30

6.4.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
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())
Jen's favorite languages are:
	Python
	Ruby

Sarah's favorite languages are:
	C

Edward's favorite languages are:
	Ruby
	Go

Phil's favorite languages are:
	Python
	Haskell

6.4.3 在字典中存储字典

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())
Username: aeinstein
	Full name: Albert Einstein
	Location: Princeton

Username: mcurie
	Full name: Marie Curie
	Location: Paris

第7章 用户输入和while循环

7.1 函数 input()的工作原理

7.1.1 编写清晰的程序

name = input("Please enter your name: ")
print("Hello, " + name + "!")
Please enter your name: jeckson.yin
Hello, jeckson.yin!
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 + "!")
If you tell us who you are, we can personalize the messages you see.
What is your first name? jeckson

Hello, jeckson!

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

age = input("How old are you? ")
print(age >= 18)
How old are you? 20



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-30-0bb6335ea0e2> in <module>
      1 age = input("How old are you? ")
----> 2 print(age >= 18)


TypeError: '>=' not supported between instances of 'str' and 'int'
age = input("How old are you? ")
age = int(age) #转换输入参数类型
print(age >= 18) 
How old are you? 20
True
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.")
How tall are you, in inches? 60

You're tall enough to ride!

7.1.3 求模运算符

print(4 % 3) #求模运算符( %)是一个很有用的工具,它将两个数相除并返回余数:

print(5 % 3)

print(6 % 3)

print(7 % 3)

1
2
0
1
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.")
Enter a number, and I'll tell you if it's even or odd: 3

The number 3 is odd.

7.1.4 在 Python 2.7 中获取输入

如果你使用的是Python 2.7,应使用函数raw_input()来提示用户输入。这个函数与Python 3
中的input()一样,也将输入解读为字符串。

7.2 while 循环简介

7.2.1 使用 while 循环

current_number = 1
while current_number <= 5:
    print(current_number)
    current_number += 1
1
2
3
4
5

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)
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 


Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 123
123

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 234
234

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. quit
quit
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)
    if message != 'quit':
        print(message)
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 123
123

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 234
234

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. quit

7.2.3 使用标志

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)
Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 123
123

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. 234
234

Tell me something, and I will repeat it back to you:
Enter 'quit' to end the program. quit

7.2.4 使用 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() + "!")
Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) erqw
I'd love to go to Erqw!

Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) 124
I'd love to go to 124!

Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) quit

7.2.5 在循环中使用 continue

current_number = 0
while current_number < 10:
    current_number += 1
    if current_number % 2 == 0:
        continue #满足条件、继续循环、不执行下面的语句
    print(current_number)
1
3
5
7
9

7.2.6 避免无限循环

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

7.3.1 在列表之间移动元素

# 首先,创建一个待验证用户列表
# 和一个用于存储已验证用户的空列表
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 删除包含特定值的所有列表元素

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 使用用户输入来填充字典

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 + ".")
What is your name? jeckson
Which mountain would you like to climb someday? yellowmount
Would you like to let another person respond? (yes/ no) yes

What is your name? cris
Which mountain would you like to climb someday? dashushan
Would you like to let another person respond? (yes/ no) yes

What is your name? eve
Which mountain would you like to climb someday? jiuhuashan
Would you like to let another person respond? (yes/ no) no

--- Poll Results ---
jeckson would like to climb yellowmount.
cris would like to climb dashushan.
eve would like to climb jiuhuashan.

第8章 函数

8.1 定义函数

def greet_user():
#"""显示简单的问候语"""
    print("Hello!")
greet_user()
Hello!

8.1.1 向函数传递信息

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

8.1.2 实参和形参

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

8.2 传递实参

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

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')
I have a hamster.
My hamster's name is Harry.
  1. 调用函数多次
    你可以根据需要调用函数任意次。
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')
describe_pet('dog', 'willie')
I have a hamster.
My hamster's name is Harry.

I have a dog.
My dog's name is Willie.
  1. 位置实参的顺序很重要
    使用位置实参来调用函数时,如果实参的顺序不正确,结果可能出乎意料:
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('harry', 'hamster')
I have a harry.
My harry's name is Hamster.

8.2.2 关键字实参
关键字实参是传递给函数的名称—值对。你直接在实参中将名称和值关联起来了,因此向函
数传递实参时不会混淆(不会得到名为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')
I have a hamster.
My hamster's name is Harry.

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

def describe_pet(pet_name, animal_type='dog'): #默认值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.

8.2.4 等效的函数调用

def describe_pet(pet_name, animal_type='dog'):
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")
    # 一条名为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')
I have a dog.
My dog's name is Willie.

I have a dog.
My dog's name is Willie.

I have a hamster.
My hamster's name is Harry.

I have a hamster.
My hamster's name is Harry.

I have a hamster.
My hamster's name is Harry.

8.2.5 避免实参错误
Python读取函数的代码,并指出我们需要为哪些形参提供实参,这提供了极大的帮助。这也
是应该给变量和函数指定描述性名称的另一个原因;如果你这样做了,那么无论对于你,还是可
能使用你编写的代码的其他任何人来说, Python提供的错误消息都将更有帮助。

8.3 返回值

8.3.1 返回简单值

 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 让实参变成可选的

def get_formatted_name(first_name, middle_name, last_name):
    #"""返回整洁的姓名"""
    full_name = first_name + ' ' + middle_name + ' ' + last_name
    return full_name.title()
musician = get_formatted_name('john', 'lee', 'hooker')
print(musician)
John Lee Hooker
def get_formatted_name(first_name, last_name, middle_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 返回字典

def build_person(first_name, last_name):
#"""返回一个字典,其中包含有关一个人的信息"""
    person = {'first': first_name, 'last': last_name}
    return person
musician = build_person('jimi', 'hendrix')
print(musician)
{'first': 'jimi', 'last': 'hendrix'}
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)
{'first': 'jimi', 'last': 'hendrix', 'age': 27}

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:")
    f_name = input("First name: ")
    l_name = input("Last name: ")
    formatted_name = get_formatted_name(f_name, l_name)
    print("\nHello, " + formatted_name + "!")
Please tell me your name:
First name: jeckson
Last name: yin

Hello, Jeckson Yin!

Please tell me your name:
First name: cris
Last name: hu

Hello, Cris Hu!

Please tell me your name:
First name: 
Last name: 

Hello,  !

Please tell me your name:
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: jeckson
Last name: yin

Hello, Jeckson Yin!

Please tell me your name:
(enter 'q' at any time to quit)
First name: cris
Last name: hu

Hello, Cris Hu!

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 在函数中修改列表

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

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

为重新组织这些代码,我们可编写两个函数,每个都做一件具体的工作。大部分代码都与
原来相同,只是效率更高。第一个函数将负责处理打印设计的工作,而第二个将概述打印了哪
些设计:

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 禁止函数修改列表

有时候,需要禁止函数修改列表。例如,假设像前一个示例那样,你有一个未打印的设计列
表,并编写了一个将这些设计移到打印好的模型列表中的函数。你可能会做出这样的决定:即便
打印所有设计后,也要保留原来的未打印的设计列表,以供备案。但由于你将所有的设计都移出
了unprinted_designs,这个列表变成了空的,原来的列表没有了。为解决这个问题,可向函数传
递列表的副本而不是原件;这样函数所做的任何修改都只影响副本,而丝毫不影响原件。
要将列表的副本传递给函数,可以像下面这样做:

function_name(list_name[:]) #切片表示法[:]创建列表的副本。
print_models(unprinted_designs[:], completed_models)
#这样函数print_models()依然能够完成其工作,因为它获得了所有未打印的设计的名称,但
#它使用的是列表unprinted_designs的副本,而不是列表unprinted_designs本身。

8.5 传递任意数量的实参

有时候,你预先不知道函数需要接受多少个实参,好在Python允许函数从调用语句中收集任
意数量的实参。

def make_pizza(*toppings): #形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中。
#"""打印顾客点的所有配料"""
    print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
('pepperoni',)
('mushrooms', 'green peppers', 'extra cheese')
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

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

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

def make_pizza(size, *toppings): #基于上述函数定义, Python将收到的第一个值存储在形参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): #函数build_profile()的定义要求提供名和姓,同时允许用户根据需要提供任意数量的名称—
# 值对。形参**user_info中的两个星号让Python创建一个名为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',
                             field='physics',
                             location='princeton')
print(user_profile)
{'first_name': 'albert', 'last_name': 'einstein', 'field': 'physics', 'location': 'princeton'}

8.6 将函数存储在模块中

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

8.6.1 导入整个模块
要让函数是可导入的,得先创建模块。 模块是扩展名为.py的文件,包含要导入到程序中的
代码。

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

#import pizza
# pizza.make_pizza(16, 'pepperoni')
# pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
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.6.2 导入特定的函数

from module_name import function_name
from module_name import function_0, function_1, function_2
from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

8.6.3 使用 as 给函数指定别名
如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短
而独一无二的别名——函数的另一个名称,类似于外号。

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

8.6.4 使用 as 给模块指定别名

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

8.6.5 导入模块中的所有函数
使用星号( *)运算符可让Python导入模块中的所有函数

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

8.7 函数编写指南

1.应给函数指定描述性名称,且只在其中使用小写字母和下划线。
2.每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。
3.给形参指定默认值时,等号两边不要有空格

第9章 类

9.1 创建和使用类

9.1.1 创建 Dog 类

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

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必不可少,还必须位于其他形参的前面。Python调用这个__init__()方法来创建Dog实例时,将自动传入实参self。
每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
我们创建Dog实例时, Python将调用Dog类的方法__init__()。我们将通过实参向Dog()传递名字和年龄; self会自动传递,因此我们不需要传递它。
每当我们根据Dog类创建实例时,都只需给最后两个形参( name和age)提供值。

此处定义的两个变量都有前缀self。以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。
self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。 self.age = age的作用与此类似。
像这样可通过实例访问的变量称为属性。

  1. 在Python 2.7中创建类
    在Python 2.7中创建类时,需要做细微的修改——在括号内包含单词object:
    class ClassName(object):
    –snip–
    这让Python 2.7类的行为更像Python 3类,从而简化了你的工作。
    在Python 2.7中定义Dog类时,代码类似于下面这样:
    class Dog(object):
    –snip–

9.1.2 根据类创建实例

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!")
        
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.")
My dog's name is Willie.
My dog is 6 years old.
  1. 访问属性
    要访问实例的属性,可使用句点表示法。在处,我们编写了如下代码来访问my_dog的属性name的值:
    my_dog.name
    句点表示法在Python中很常用,这种语法演示了Python如何获悉属性的值。在这里, Python先找到实例my_dog,再查找与这个实例相关联的属性name。

  2. 调用方法
    根据Dog类创建实例后,就可以使用句点表示法来调用Dog类中定义的任何方法。下面来让小狗蹲下和打滚:
    要调用方法,可指定实例的名称(这里是my_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!")
        
my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()
Willie is now sitting.
Willie rolled over!
  1. 创建多个实例
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!")

my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()
print("\nYour dog's name is " + your_dog.name.title() + ".")
print("Your dog is " + str(your_dog.age) + " years old.")
your_dog.sit()
My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.

Your dog's name is Lucy.
Your dog is 3 years old.
Lucy is now sitting.

9.2 使用类和实例

9.2.1 Car 类

class Car():
#"""一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
    #"""初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
    def get_descriptive_name(self):
    #"""返回整洁的描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
2016 Audi A4

9.2.2 给属性指定默认值

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()
2016 Audi A4
This car has 0 miles on it.

9.2.3 修改属性的值

  1. 直接修改属性的值
    要修改属性的值,最简单的方式是通过实例直接访问它。
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()

my_new_car.odometer_reading = 23
my_new_car.read_odometer()
2016 Audi A4
This car has 0 miles on it.
This car has 23 miles on it.
  1. 通过方法修改属性的值
    如果有替你更新属性的方法,将大有裨益。这样,你就无需直接访问属性,而可将值传递给一个方法,由它在内部进行更新。
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):
        #"""将里程表读数设置为指定的值"""
        self.odometer_reading = mileage
        
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

my_new_car.update_odometer(23)
my_new_car.read_odometer()
2016 Audi A4
This car has 0 miles on it.
This car has 23 miles on it.
  1. 通过方法对属性的值进行递增
    有时候需要将属性值递增特定的量,而不是将其设置为全新的值。
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):
        #"""将里程表读数设置为指定的值"""
        self.odometer_reading = mileage
    def increment_odometer(self, miles):
    #"""将里程表读数增加指定的量"""
        self.odometer_reading += miles
my_used_car = Car('subaru', 'outback', 2013)
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
2013 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.

9.3 继承

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

9.3.1 子类的方法__init__()
创建子类的实例时, Python首先需要完成的任务是给父类的所有属性赋值。

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
class ElectricCar(Car):
    #"""电动汽车的独特之处"""
    def __init__(self, make, model, year):
    #"""初始化父类的属性"""
        super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
2016 Tesla Model S

9.3.2 Python 2.7 中的继承

在Python 2.7中,继承语法稍有不同, ElectricCar类的定义类似于下面这样:
class Car(object):
    def __init__(self, make, model, year):
    --snip--
class ElectricCar(Car):
    def __init__(self, make, model, year):
    super(ElectricCar, self).__init__(make, model, year)
    --snip--
函数super()需要两个实参:子类名和对象self。为帮助Python将父类和子类关联起来,
这些实参必不可少。另外,在Python 2.7中使用继承时,务必在定义父类时在括号内指定object

9.3.3 给子类定义属性和方法
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法

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
class ElectricCar(Car):
    #"""电动汽车的独特之处"""
    def __init__(self, make, model, year):
    #电动汽车的独特之处初始化父类的属性,再初始化电动汽车特有的属性
        super().__init__(make, model, year)
        self.battery_size = 70
    def describe_battery(self):
    #"""打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
2016 Tesla Model S
This car has a 70-kWh battery.

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

假设Car类有一个名为fill_gas_tank()的方法,它对全电动汽车来说毫无意义,因此你可能想重写它。
下面演示了一种重写方式:

def ElectricCar(Car):
    --snip--
    def fill_gas_tank():
        #"""电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")

9.3.5 将实例用作属性
使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。
在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。
你可以将大型类拆分成多个协同工作的小类。

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
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.")
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()
2016 Tesla Model S
This car has a 70-kWh battery.

9.3.6 模拟实物

9.4 导入类

9.4.1 导入单个类

from car import Car

9.4.2
在一个模块中存储多个类虽然同一个模块中的类之间应存在某种相关性,但可根据需要在一个模块中存储任意数量的类。

9.4.3 从一个模块中导入多个类

from car import Car, ElectricCar

9.4.4 导入整个模块

import car

my_beetle = car.Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())

my_tesla = car.ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())

9.4.5 导入模块中的所有类

from module_name import *

不推荐使用这种导入方式,其原因有二。首先,如果只要看一下文件开头的import语句,就
能清楚地知道程序使用了哪些类,将大有裨益;但这种导入方式没有明确地指出你使用了模块中
的哪些类。这种导入方式还可能引发名称方面的困惑。如果你不小心导入了一个与程序文件中其
他东西同名的类,将引发难以诊断的错误。这里之所以介绍这种导入方式,是因为虽然不推荐使
用这种方式,但你可能会在别人编写的代码中见到它。

9.4.6 在一个模块中导入另一个模块

9.4.7 自定义工作流程

9.5 Python 标准库

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

9.6 类编码风格

你必须熟悉有些与类相关的编码风格问题,在你编写的程序较复杂时尤其如此。
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。
实例名和模块名都采用小写格式,并在单词之间加上下划线。
对于每个类,都应紧跟在类定义后面包含一个文档字符串。
这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。
每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,
再添加一个空行,然后编写导入你自己编写的模块的import语句。在包含多条import语句的程序中,
这种做法让人更容易明白程序使用的各个模块都来自何方。

第10章 文件和异常

10.1 从文件中读取数据

10.1.1 读取整个文件

with open('E:/test/pi_digits.txt') as file_object: 
    #函数open()接受一个参数:要打开的文件的名称。open('pi_digits.txt')返回一个表示文件pi_digits.txt的对象; 
    #Python将这个对象存储在我们将在后面使用的变量中
    #关键字with在不再需要访问文件后将其关闭。
    contents = file_object.read()
    #方法read()读取这个文件的全部内容,并将其作为一个长长的字符串存储在变量contents中
    print(contents)
   
3.1415926535
8979323846
2643383279
with open('E:/test/pi_digits.txt') as file_object: 
    #该输出唯一不同的地方是末尾多了一个空行。
    #因为read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删
    #除多出来的空行,可在print语句中使用rstrip()
    contents = file_object.read() 
    print(contents.rstrip())
3.1415926535
8979323846
2643383279

10.1.2 文件路径

linux&mac os斜杠( /)
windows反斜杠( \)

10.1.3 逐行读取
读取文件时,常常需要检查其中的每一行:你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。

filename = 'E:/test/pi_digits.txt'
with open(filename) as file_object:
    for line in file_object:
        print(line)
3.1415926535

8979323846

2643383279

为何会出现这些空白行呢?因为在这个文件中,每行的末尾都有一个看不见的换行符,而
print语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print
语句。要消除这些多余的空白行,可在print语句中使用rstrip()

filename = 'E:/test/pi_digits.txt'
with open(filename) as file_object:
    for line in file_object:
        print(line.rstrip())
3.1415926535
8979323846
2643383279

10.1.4 创建一个包含文件各行内容的列表

filename = 'E:/test/pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
for line in lines: #方法readlines()从文件中读取每一行,并将其存储在一个列表中;接下来,该列表被
                    #存储到变量lines中;在with代码块外,我们依然可以使用这个变量
        print(line.rstrip())
3.1415926535
8979323846
2643383279

10.1.5 使用文件的内容

filename = 'E:/test/pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
pi_string = ''
for line in lines:
    pi_string += line.rstrip()
print(pi_string)
print(len(pi_string))
3.141592653589793238462643383279
32

10.1.6 包含一百万位的大型文件

filename = 'E:/test/pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
pi_string = ''
for line in lines:
    pi_string += line.strip()
print(pi_string[:20] + "...") #只打印到20位
print(len(pi_string))
3.141592653589793238...
32

10.1.7 圆周率值中包含你的生日吗

filename = 'E:/test/pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
pi_string = ''
for line in lines:
    pi_string += line.rstrip()
birthday = input("Enter your birthday, in the form mmddyy: ")
if birthday in pi_string:
    print("Your birthday appears in the first million digits of pi!")
else:
    print("Your birthday does not appear in the first million digits of pi.")
Enter your birthday, in the form mmddyy: 0213
Your birthday appears in the first million digits of pi!

10.2 写入文件

10.2.1 写入空文件

filename = 'E:/test/programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.") #以写入( 'w')模式打开文
                                             #件时千万要小心,因为如果指定的文件已经存在, Python将在返回文件对象前清空该文件。

10.2.2 写入多行
函数write()不会在你写入的文本末尾添加换行符,因此如果你写入多行时没有指定换行符,
文件看起来可能不是你希望的那样:

要让每个字符串都单独占一行,需要在write()语句中包含换行符:

filename = 'E:/test/programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.\n")
    file_object.write("I love creating new games.\n")

10.2.3 附加到文件

filename = 'E:/test/programming.txt'
with open(filename, 'a') as file_object:
    file_object.write("I also love finding meaning in large datasets.\n")
    file_object.write("I love creating apps that can run in a browser.\n")

10.3 异常

10.3.1 处理 ZeroDivisionError 异常

print(5/0)
---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

<ipython-input-75-fad870a50e27> in <module>
----> 1 print(5/0)


ZeroDivisionError: division by zero

10.3.2 使用 try-except 代码块
当你认为可能发生了错误时,可编写一个try-except代码块来处理可能引发的异常。你让
Python尝试运行一些代码,并告诉它如果这些代码引发了指定的异常,该怎么办。

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
You can't divide by zero!

10.3.3 使用异常避免崩溃
发生错误时,如果程序还有工作没有完成,妥善地处理错误就尤其重要。这种情况经常会出
现在要求用户提供输入的程序中;如果程序能够妥善地处理无效输入,就能再提示用户提供有效
输入,而不至于崩溃。

print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
    first_number = input("\nFirst number: ")
    if first_number == 'q':
        break
    second_number = input("Second number: ")
    if second_number == 'q':
        break
    answer = int(first_number) / int(second_number)
    print(answer)
Give me two numbers, and I'll divide them.
Enter 'q' to quit.

First number: 5
Second number: 0



---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

<ipython-input-77-2d52e39c3fbf> in <module>
      8     if second_number == 'q':
      9         break
---> 10     answer = int(first_number) / int(second_number)
     11     print(answer)


ZeroDivisionError: division by zero

10.3.4 else 代码块

print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
    first_number = input("\nFirst number: ")
    if first_number == 'q':
        break
    second_number = input("Second number: ")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0!")
    else:
        print(answer)
Give me two numbers, and I'll divide them.
Enter 'q' to quit.

First number: 5
Second number: 0
You can't divide by 0!

First number: 5
Second number: 2
2.5

First number: q

10.3.5 处理 FileNotFoundError 异常

filename = 'alice.txt'
with open(filename) as f_obj:
    contents = f_obj.read()
---------------------------------------------------------------------------

FileNotFoundError                         Traceback (most recent call last)

<ipython-input-81-665c307cd5e9> in <module>
      1 filename = 'alice.txt'
----> 2 with open(filename) as f_obj:
      3     contents = f_obj.read()


FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
filename = 'alice.txt'
try:
    with open(filename) as f_obj:
        contents = f_obj.read()
except FileNotFoundError:
    msg = "Sorry, the file " + filename + " does not exist."
    print(msg)
Sorry, the file alice.txt does not exist.

10.3.6 分析文本

filename = 'E:/test/programming.txt'
try:
    with open(filename) as f_obj:
        contents = f_obj.read()
except FileNotFoundError:
    msg = "Sorry, the file " + filename + " does not exist."
    print(msg)
else:
# 计算文件大致包含多少个单词
    words = contents.split()
    num_words = len(words)
    print("The file " + filename + " has about " + str(num_words) + " words.")
The file E:/test/programming.txt has about 44 words.

10.3.7 使用多个文件

def count_words(filename):
#计算一个文件大致包含多少个单词
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + " does not exist."
        print(msg)
    else:
    # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) +" words.")
filename = 'E:/test/programming.txt'
count_words(filename)
The file E:/test/programming.txt has about 44 words.
def count_words(filename):
#计算一个文件大致包含多少个单词
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + " does not exist."
        print(msg)
    else:
    # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) +" words.")
filenames = ['E:/test/programming.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
    count_words(filename)
The file E:/test/programming.txt has about 44 words.
Sorry, the file moby_dick.txt does not exist.
Sorry, the file little_women.txt does not exist.

10.3.8 失败时一声不吭

def count_words(filename):
#计算一个文件大致包含多少个单词
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        pass
    else:
    # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) +" words.")
filenames = ['E:/test/programming.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
    count_words(filename)
The file E:/test/programming.txt has about 44 words.

10.3.9 决定报告哪些错误

10.4 存储数据

10.4.1 使用 json.dump()和 json.load()

import json
numbers = [2, 3, 5, 7, 11, 13, 15]
filename = 'E:/test/numbers.json'
with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)
import json
filename = 'E:/test/numbers.json'
with open(filename) as f_obj:
    numbers = json.load(f_obj)
print(numbers)
[2, 3, 5, 7, 11, 13, 15]

10.4.2 保存和读取用户生成的数据

import json
username = input("What is your name? ")
filename = 'E:/test/username.json'
with open(filename, 'w') as f_obj:
    json.dump(username, f_obj)
print("We'll remember you when you come back, " + username + "!")
What is your name? EVE
We'll remember you when you come back, EVE!
import json
filename = 'E:/test/username.json'
with open(filename) as f_obj:
    username = json.load(f_obj)
print("Welcome back, " + username + "!")
Welcome back, EVE!
import json
# 如果以前存储了用户名,就加载它
# 否则,就提示用户输入用户名并存储它
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)
        print("We'll remember you when you come back, " + username + "!")
else:
    print("Welcome back, " + username + "!")
Welcome back, Jeckson!

10.4.3 重构

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)
            print("We'll remember you when you come back, " + username + "!")
    else:
        print("Welcome back, " + username + "!")
greet_user()
Welcome back, EVE!
import json
def get_stored_username():
#"""如果存储了用户名,就获取它"""
    filename = 'username.json'
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError:
        return None
    else:
        return username
def greet_user():
#"""问候用户,并指出其名字"""
    username = get_stored_username()
    if username:
        print("Welcome back, " + username + "!")
    else:
        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 + "!")
greet_user()
Welcome back, Jeckosn!
import json
def get_stored_username(): #读取老用户
#"""如果存储了用户名,就获取它"""
    filename = 'username.json'
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError:
        return None
    else:
        return username
def get_new_username(): #存储新用户
#"""提示用户输入用户名"""
    username = input("What is your name? ")
    filename = 'username.json'
    with open(filename, 'w') as f_obj:
        json.dump(username, f_obj)
    return username
def greet_user(): #打招呼
#"""问候用户,并指出其名字"""
    username = get_stored_username()
    if username:
        print("Welcome back, " + username + "!")
    else:
        username = get_new_username()
        print("We'll remember you when you come back, " + username + "!")
greet_user()
Welcome back, Jeckson.yin!

第11章 测试代码

11.1 测试函数

11.1.1 单元测试和测试用例
Python标准库中的模块unittest提供了代码测试工具。 单元测试用于核实函数的某个方面没
有问题; 测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。
良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。 全覆盖式测
试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可
能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。

11.1.2 可通过的测试
创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测
试就很简单了。要为函数编写测试用例,可先导入模块unittest以及要测试的函数,再创建一个
继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。

import unittest
from name_function import get_formatted_name
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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值