python入门笔记
学习资料:
Python编程:从入门到实践(第2版)
一、 起步
1.1 搭建编程环境
略
二、变量和简单数据类型
2.1 直接输出
print("Hello python world!")
2. 2 变量输出
messages="hello python world" print(messages)
#变量名可以数字、英文、下划线,但是不能数字开头
2.3字符串
2.3.1使用方法修改字符串的大小写
print(messages.title()) #首字母大写 print(name1.upper()) #全大写 print(name1.lower()) #全小写 first_name = "ada" last_name = "lovelace" full_name = f"{first_name} {last_name}" print(full_name) print(f"Hello, {full_name.title()}!")
2.3.2在字符串中使用变量
messages = f"Hello, {full_name.title()}!" print(messages)
2.3.3使用制表符或换行符添加空白
print("Languages:\n\tPython\n\tC\n\tJavaScript")
2.3.4删除空白
favorite_language = ' python ' print(favorite_language) print(favorite_language.rstrip()) #剔除右边空白 print(favorite_language.lstrip()) #剔除左边空白 print(favorite_language.strip()) #剔除两边空白
2.4数
2.4.1整数
a=2+3 print(a) print(2+5)
+加法 -减法 *乘法 /除法 **乘方
2.4.2 浮点数
print(0.1+0.1)
#无论是哪种运算,只要操作数是浮点数,Python得到的总是浮点数
2.4.4 数中的下划线
universe_age=14_000_000_000 print(universe_age)
结果中不会包含下划线,书写很大的数时,可使用下划线将其中的数字分组,使其更清晰易读,但只有Python 3.6 和更高的版本支持
2.4.5 同时给多个变量赋值
x,y,z=0,1,2 print(x,y,z) print(x)
2.4.6常量
#常规来讲全大写的变量看作为常量,希望某个值在程序的整个生命周期不变!相反
MAX_CONNECTIONS = 5000
print(MAX_CONNECTIONS)
三、列表
3.1列表
#方括号标识列表,逗号隔开
bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles[0]) print(bicycles[0].title()) print(bicycles[-1].title()) print(bicycles[-2].title()) message = "my first bicycle was a " + bicycles[0].title() + "." print(message)
3.2增删改元素
motorcycles = ['honda','yamaha', 'suzuki']
增
motorcycles.insert(3,'ducati')
print(motorcycles)
motorcycles = ['honda','yamaha', 'suzuki']
motorcycles.append('ducati')
print(motorcycles)
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki', 'ducati']
删
del motorcycles[0] #删除左边第一个 print(motorcycles[0]) #查看左边第一个
['yamaha']
根据位置删
first_owned = motorcycles.pop(0) print(first_owned) #显示第一个 print(motorcycles)
honda
['yamaha']
根据值删除
motorcycles = ['honda', 'yamaha,' 'suzuki', 'ducati'] print(motorcycles) motorcycles.remove('ducati') #注:remove()方法只删除第一个指定的值
motorcycles = ['honda', 'yamaha,' 'suzuki', 'ducati'] too_expensive = 'ducati' motorcycles.remove(too_expensive) print(motorcycles) print("\nA " + too_expensive.title() + "is too expensive for me.")
['honda', 'yamaha,suzuki', 'ducati']
['honda', 'yamaha,suzuki']
A Ducatiis too expensive for me.
弹出
motorcycles = ['honda','yamaha', 'suzuki'] print(motorcycles) popped_motorcycles = motorcycles.pop() #pop是删除末尾操作 print(popped_motorcycles) #显示的是删的那个一个 print(motorcycles) #剩下的
['honda', 'yamaha', 'suzuki']
suzuki
['honda', 'yamaha']
改
motorcycles[0]='ducati'
3.3组织列表
3.3.1使用方法sort()对列表永久排序
cars = ['bmw', 'audi', 'toyota', 'subaru'] print(cars)
#['bmw', 'audi', 'toyota', 'subaru']
cars.sort() print(cars)
#['audi', 'bmw', 'subaru', 'toyota']
按照相反位置
cars.sort(reverse=True) print(cars)
#['toyota', 'subaru', 'bmw', 'audi']
3.2.2使用函数sorted()对列表临时排序
cars = ['bmw', 'audi', 'toyota', 'subaru'] print(cars)
#['bmw', 'audi', 'toyota', 'subaru']
print(sorted(cars)) print(cars)
#['audi', 'bmw', 'subaru', 'toyota']
#['bmw', 'audi', 'toyota', 'subaru']
#只有第一次是经过排序的
3.3.3倒着打印列表-reverse()永久修改
cars = ['bmw', 'audi', 'toyota', 'subaru'] print(cars) cars.reverse() print(cars) cars.reverse() print(cars)
#['bmw', 'audi', 'toyota', 'subaru']
#['subaru', 'toyota', 'audi', 'bmw']
#['bmw', 'audi', 'toyota', 'subaru']
#进行了翻转
3.3.4确定列表的长度-len()
cars = ['bmw', 'audi', 'toyota', 'subaru'] print(len(cars))
4
四、操作列表
4.1遍历整个列表
magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician)
alice
david
carolina
4.1.3在for循环结束后执行一些操作
magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(f"{magician.title()}that was a great trick!\nI can't wait to see your next trick,{magician.title()}.\n") print("Thank you, everyone.That was a great magic show!")
Alicethat was a great trick!
I can't wait to see your next trick,Alice.
Davidthat was a great trick!
I can't wait to see your next trick,David.
Carolinathat was a great trick!
I can't wait to see your next trick,Carolina.
Thank you, everyone.That was a great magic show!
4.3创建数值列表
4. 3. 1 使用函数range()
for value in range(1, 5): print(value)
#
1
2
3
4
实际打印1-4,这是编程语言中常见的差一行为的结果。 函数range() 让Python从指定的第一个值开始数,并在到达你指定的第二个值时停 止。因为它在第二个值处停止,所以输出不包含该值(这里为5)
4. 3. 2 使用range() 创建数字列表
numbers = list(range(1,6)) print(numbers)
[1, 2, 3, 4, 5]
#使用函数range() 时,还可指定步长。为此,可给这个函数指定第三个参数, Python将根据这个步长来生成数。
#例如,下面的代码打印1~10的偶数:
even_numbers = list(range(2, 11, 2)) print(even_numbers)
#[2, 4, 6, 8, 10]
#奇数
even_numbers = list(range(1, 11, 2)) print(even_numbers)
#[1, 3, 5, 7, 9]
#创建一个列表,包括1~10的平方
squares=[] for value in range(1,11): square=value ** 2 squares.append(square) print(squares)
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
#简写
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(max(digits)) #9 #最小 print(min(digits)) #0 #总和 print(sum(digits)) #45
#4.3.4列表解析
squares=[value ** 2 for value in range(1,11)] print(squares)
#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
4.4使用列表的一部分
4.4.1切片
players = ['charles', 'martina', 'michael', 'florence', 'eli'] print(players[1:3]) #0是第一个,打印2-4个中间的值
#['martina', 'michael']
#打印前四个 print(players[:4])
#['charles', 'martina', 'michael', 'florence']
#打印从2个之后的所有
print(players[2:])
#负数索引,最后4个
print(players[-4:])
#每隔2个提取一个
print(players[0:4:2])
#['charles', 'michael']
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())
4.4.3复制列表
my_foods = ['pizza', 'falafel', 'carrot cake'] friend_foods=my_foods[:] my_foods.append('cannoli') friend_foods.append('ice cream') print(my_foods) print(friend_foods)
#['pizza', 'falafel', 'carrot cake', 'cannoli']
#['pizza', 'falafel', 'carrot cake', 'ice cream']
#如果使用friend_foods=my_foods,最终结果会一样。
4.5元组
4.5.1定义元组-不可变的列表
dimensions=(200,50) print(dimensions[0]) print(dimensions[1])
不能以索引的方式去赋值
dimensions[0] = 250
报错
4.5.2遍历元组中的所有值
dimensions=(200,50) for dimension in dimensions: print(dimension)
4.5.3修改元组变量
dimensions=(200,50) for dimension in dimensions: print(dimension) dimensions=(400,100) for dimension in dimensions: print(dimension) #可以重新赋值
五、if语句
5.1一个简单的示例
cars = ['audi', 'bmw', 'subaru', 'toyota'] for car in cars: if car == 'bmw': print(car.upper()) else: print(car.title())
5.2条件测试 True False
5.2.1检查是否相等
car='bmw' print(car=='bmw') #True print(car=='amw') #False
5.2.2 检查是否相等时忽略大小写
car='Amw' print(car=='amw') #False print(car.lower()=='amw') #True
5.2.3检查是否不相等
requested_topping = 'mushrooms' if requested_topping != 'anchovies': print("Hold the anchovies")
5. 2. 4 数值比较
age=18 print(age == '18') #False
answer=17 if answer != 42: print("That is not the correct answer. Please try again!") #That is not the correct answer. Please try again!
小于、小于等于、大于、大于等于
> >= > >=
5. 2. 5 检查多个条件
使用and 检查多个条件
age_0=22 age_1=18 print(age_0>=21 and age_1>=21) #False print(age_0>21 and age_1<21) #True print((age_0>21) and (age_1<21)) #True
使用or检查多个条件
print (age_0 >=21 or age_1 >=21) #True #5. 2. 6 检查特定值是否包含在列表中 print("asd") requested_toppings = ['mushrooms', 'onions', 'pineapple'] print('mushrooms' in requested_toppings) #True
5. 2. 6 检查特定值是否包含在列表中
requested_toppings = ['mushrooms', 'onions', 'pineapple'] print("mushrooms' in requested_toppings") #True print("pepperoni' in requested_toppings") #False
5. 2. 7 检查特定值是否不包含在列表中
banned_users = ['andrew', 'carolina', 'david'] print("aa not in banned_users") #True user='marie' if 'user' not in banned_users: print(f"{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!") print("Have you registered to vote yet?")
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!")
5.3.3 if-elif-else 结构
#4岁以下免费; #4~18岁收费25美元; 18岁(含)以上收费40美元。
age=22 if age >18: print("$40") elif age <4: print("$0") else: print("$25")
#简洁:
if age >18: price=40 elif age <4: price=0 else: price=25 print(f"Your admission cost is ${price}")
5.3.4使用多个elif代码块
假设对65岁以上老人半价
if age <4: price=0 elif age <18: price=25 elif age <65: price=40 else: print=25 print(f"Your admission cost is ${price}")
5.3.5 省略else 代码块
if age <4: price=0 elif age <18: price=25 elif age <65: price=40 elif age >=65: print=25 print(f"Your admission cost is ${price}")
5.3.6测试多个条件
#如果顾客点了两种配料,就需要确保在其比萨中 包含这些配料:
requested_toppings = ['mushrooms', 'extra cheese'] if 'mushrooms' in requested_toppings: print("Adding mushrooms.") if 'pepperoni' in requested_toppings: print("Adding pepperoni.") if 'extra cheese' in requested_toppings: print("Adding extra cheese.") print("\nFinished making your pizza!")
5. 4 使用if 语句处理列表
5. 4. 1 检查特殊元素
每添加一种配料都打印一 条消息
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese'] for requested_topping in requested_toppings: print(f"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(f"Adding {requested_topping}.") print("\nFinished making your pizza!")
#青椒无库存
5. 4. 2 确定列表不是空的
下面在制作比萨前检查顾客点的配料列表是否为空。如果列表为空,就向顾客确认 是否要点原味比萨;如果列表不为空,就像前面的示例那样制作比萨:
requested_toppings = [] if requested_toppings: for requested_topping in requested_toppings: print(f"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(f"Adding {requested_topping}.") else: print(f"Sorry, we don't have {requested_topping}.") print("\nFinished making your pizza!")
六、字典
#字典可存储的信息量几乎不受限制,存储方式是K/V
6. 1 一个简单的字典
alien_0 = {'color': 'green', 'points': 5} print(alien_0['color'])
#green
6. 2 使用字典
字典 是一系列键值对 。每个键 都与一个值相关联,你可使用键来访 问相关联的值。与键相关联的值可以是数、字符串、列表乃至字典。事实上,可将 任何Python对象用作字典中的值。
6. 2. 2 添加键值对
alien_0['x_position'] = 0 alien_0['y_position'] = 25 print(alien_0)
#{'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'] = 'yellow' print(alien_0)
#{'color': 'yellow', 'points': 5}
对一个能够以不同速度移动的外星人进行位置跟踪。为 此,我们将存储该外星人的当前速度,并据此确定该外星人将向右移动多远
alien_0 = {'x_position': 0, 'y_position': 25} speeds=['slow','medium','3'] for speed in speeds : if speed == 'slow': x_increment = 1 alien_0['x_position'] = alien_0['x_position'] + x_increment elif speed == 'medium': x_increment = 2 alien_0['x_position'] = alien_0['x_position'] + x_increment else: x_increment = 3 alien_0['x_position'] = alien_0['x_position'] + x_increment print(f"New position: {alien_0['x_position']}")
#New position: 6
alien_0 = {'x_position': 0, 'y_position': 25} speeds=['5','6','-2'] for speed in speeds : alien_0['x_position'] = alien_0['x_position'] + x_increment print(f"New position: {alien_0['x_position']}")
#New position: 9
6. 2. 5 删除键值对
alien_0 = {'color': 'green', 'points': 5} del alien_0['points'] print(alien_0)
#{'color': 'green'}
6. 2. 6 由类似对象组成的字典
favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phphil': 'python',} print(favorite_languages) language = favorite_languages['jen'].title() print(f"Sarah's favorite language is {language}.")
{'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phphil': 'python'}
Sarah's favorite language is Python.
6. 2. 7 使用get() 来访问值
alien_0 = {'color': 'green', 'speed': 'slow'} print(alien_0['points']) #如果没有就回返回报错
#第10章会说明如何处理,但就字典而言可以使用方法get,不能存在时返回一个默认值
print(alien_0.get('points', 'No point value assigned.')) point_value = alien_0.get('points', 'No point value assigned.') print(point_value)
#No point value assigned.
6. 3 遍历字典
user_0 = {'username': 'efermi', 'first': 'enrico', 'last': 'fermi', } for key, value in user_0.items(): print(f"\nKey: {key}") print(f"Value: {value}") Key: username Value: efermi Key: first Value: enrico Key: last Value: fermi
6. 3. 2 遍历字典中的所有键
for k in user_0.keys(): print(f"\n{k.title()}") Username First Last
6. 3. 3 按特定顺序遍历字典中的所有键
#一种办法是在for 循环中对返回的键进行排序。为此,可 使用函数sorted() 来获得按特定顺序排列的键列表的副本:
favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python'} for name in sorted(favorite_languages.keys()): print(f"P{name.title()}, thank you for taking the poll.")
PEdward, thank you for taking the poll.
PJen, thank you for taking the poll.
PPhil, thank you for taking the poll.
PSarah, thank you for taking the poll.
使用set()去重遍历
favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python'} for language in set(favorite_languages.values()): print(language.title())
Ruby
C
Python
#注意 可使用一对花括号直接创建集合,并在其中用逗号分隔元素:
#集合和字典很容易混淆,因为它们都是用一对花括号定义的。当花括号内没有 键值对时,定义的很可能是集合。不同于列表和字典,集合不会以特定的顺序 存储元素。
6.4嵌套
#有时候,需要将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为 嵌套 。你可以在列表中嵌套字典、在字典中嵌套列表甚至在字典中嵌套字典。正如 下面的示例将演示的,嵌套是一项强大的功能。
6. 4. 1 字典列表
#字典alien_0 包含一个外星人的各种信息,但无法存储第二个外星人的信息,更别 说屏幕上全部外星人的信息了。如何管理成群结队的外星人呢?一种办法是创建一 个外星人列表,其中每个外星人都是一个字典,包含有关该外星人的各种信息。例 如,下面的代码创建一个包含三个外星人的列表:
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}
#更符合现实的情形是,外星人不止三个,且每个外星人都是使用代码自动生成的。
#在下面的示例中,使用range() 生成了30个外星人:
aliens = [] 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) # {'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'}
#前5个外星人信息都是一样的
print(f"Total number of aliens: {len(aliens)}") #显示总共多少个外星人 Total number of aliens: 30
#使用切片修改前3个外星人信息,然后判断前5个外星人信息并且修改其他k的v
aliens = [] for alien_number in range(30): new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} aliens.append(new_alien) for alien in aliens[:3]: if alien['color'] == 'green': alien['color'] = 'yellow' for alien in aliens[:5]: if alien['color'] == 'green': alien['speed'] = 'medium' elif alien['color'] == 'yellow': alien['speed'] = 'fast' for alien in aliens[:10]: print(alien) # {'color': 'yellow', 'points': 5, 'speed': 'fast'} {'color': 'yellow', 'points': 5, 'speed': 'fast'} {'color': 'yellow', 'points': 5, 'speed': 'fast'} {'color': 'green', 'points': 5, 'speed': 'medium'} {'color': 'green', 'points': 5, 'speed': 'medium'} {'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'}
6. 4. 2 在字典中存储列表
pizza = { 'crust': 'thick', 'toppings': ['mushrooms', 'extra cheese'],} print(f"You ordered a {pizza['crust']}-crust pizza " "with the following toppings:") for topping in pizza['toppings']: print(f"{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(f"\n{name.title()}'s favorite languages are:") for language in languages: print(f"\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(f"\nUsername:{username}") full_name=f"{user_info['first']} {user_info['last']}" print(f"Full name:{full_name.title()}") print(f"Location:{user_info['location'].title()}")
#
Username:aeinstein
Full name:Albert Einstein
Location:Princeton
Username:mcurie
Full name:Marie Curie
Location:Paris
七、用户输入和while 循环
7. 1 函数input() 的工作原理
任务:下面的程序让用户输入一些文本,再将这些文本呈现给用户:
message = input("Tell me something, and I will repeat it back to you: ") print(message)
7. 1. 1 编写清晰的程序
name = input("Please enter your name: ") print(f"\nHello, {name}!")
7. 1. 2 使用int() 来获取数值输入
age = input("How old are you? ") print(age) #但如果试图将 输入作为数来使用,就会引发错误,需要明确字符串类型 age = input("How old are you? ") age = int(age) print(age >= 18) #True #询问用户身高多少 height = input("How tall are you, in inches? ") height = int(height) if height >= 48: print("\nYou're tall enough to ride!") else: print("\nYou'll be able to ride when you're a little older.")
7. 1. 3 求模运算符
#相除返回余数 number=int(8) if number % 2 == 0: print("even") else: print("odd")
7. 2 while 循环简介
for 循环用于针对集合中的每个元素都执行一个代码块,而while 循环则不断运 行,直到指定的条件不满足为止。
7. 2. 1 使用while 循环
current_number=1 while current_number <= 5 : print(current_number) current_number += 1 #or current_number = current_number + 1 1 2 3 4 5
7. 2. 2 让用户选择何时退出
#空字符串 message = "" #空列表 message = [] #空字典 message = {}
prompt = "\nTell me something,and i will repeat it back to you:" prompt += "\n Enter 'quit' to end the program." message = "" while message != 'quit': message = input(prompt) if message != 'quit': print(message) else: print("bye")
#必须输入quit,否则不断循环
7. 2. 3 使用标志(flag)
#可以让程序判断标识为True和False
prompt = "\nTell me something,and i will repeat it back to you:" prompt += "\n Enter 'quit' to end the program." active = True while active: message = input(prompt) if message == 'quit': active = False else: print(message) #效果同上,只有输入quit才会退出,负责打印输入的内容
7. 2. 4 使用break 退出循环
#在任何Python循环中都可以使用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(f"i'd love to go to {city.title()}")
7. 2. 5 在循环中使用continue
break - 不执行余下的代码,退出整个循环
continue - 不执行余下的代码,返回循环的开头
#不显示偶数
current_number = 0 while current_number < 10: current_number += 1 if current_number % 2 == 0: continue print(current_number)
7. 2. 6 避免无限循环
x = 1 while x <= 5: print(x) # x += 1 #错误的写法,忘记 +1 x = 1 while x <= 5: print(x)
7. 3 使用while 循环处理列表和字典
7. 3. 1 在列表之间移动元素
#假设有一个列表包含新注册但还未验证的网站用户。验证这些用户后,如何将他们 移到另一个已验证用户列表中呢?
#一种办法是使用一个while 循环,在验证用户的 同时将其从未验证用户列表中提取出来,再将其加入另一个已验证用户列表中。代 码可能类似于下面这样:
#首先,创建一个待验证用户列表
# 和一个用于存储已验证用户的空列表。
unconfirmed_users = ['alice', 'brian', 'candace'] confirmed_users = [] while unconfirmed_users: current_user = unconfirmed_users.pop() print(f"Verifying user:append{current_user}") confirmed_users.append(current_user) #显示已验证的用户 print("\nThe following users have been confirmed:") for confirmed_user in confirmed_users: print(confirmed_user.title()) #顺序是pop弹出末尾,所以是反着显示的
Verifying user:appendcandace
Verifying user:appendbrian
Verifying user:appendalice
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) # Alice ['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(f"{name} would like to climb {response}.")
八、函数
8. 1 定义函数
def greet_user(): print("Hello!") greet_user() #Hello!
8. 1. 1 向函数传递信息
def greet_user(username): """显示简单的问候语。""" print(f"Hello, {username.title()}!") greet_user('jesse') #Hello, Jesse!
8. 1. 2 实参和形参
#在函数greet_user() 的定义中,变量username 是一个形参 (parameter), 即函数完成工作所需的信息。
#在代码greet_user('jesse') 中,值'jesse'是一个实参 (argument),即调用函数时传递给函数的信息。
#调用函数时,将要让函 数使用的信息放在圆括号内。
#在greet_user('jesse') 中,将实参'jesse' 传 递给了函数greet_user() ,这个值被赋给了形参username 。
8. 2 传递实参
#函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递 实参的方式很多:可使用位置实参 ,这要求实参的顺序与形参的顺序相同;也可使 用关键字实参 ,其中每个实参都由变量名和值组成;还可使用列表和字典。下面依 次介绍这些方式。
8. 2. 1 位置实参
def describe_pet(animal_type, pet_name): """显示宠物的信息。""" print(f"\nI have a {animal_type}.") print(f"My {animal_type}'s name is {pet_name.title()}.") describe_pet('hamster', 'harry')
#
I have a hamster.
My hamster's name is Harry.
8. 2. 2 关键字实参
#明确指出关联,可以不必
def describe_pet(animal_type, pet_name): """显示宠物的信息。""" print(f"\nI have a {animal_type}.") print(f"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 默认值
def describe_pet(pet_name, animal_type='dog'): """显示宠物的信息。""" print(f"\nI have a {animal_type}.") print(f"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(f"\nI have a {animal_type}.") print(f"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 避免实参错误
#调用时如果无值,需要确认所有形参是否有默认值,否则报错
8. 3 返回值
8. 3. 1 返回简单值
#将名字通过函数返回拼接和大写
def get_formatted_name(first_name,last_name): #返回全名 full_name=f"{first_name} {last_name}" return full_name.title() musician = get_formatted_name('jimi', 'hendrix') print(musician) #或者 print(get_formatted_name('jimi', 'hendrix') )
# Jimi Hendrix Jimi Hendrix
8. 3. 2 让实参变成可选的
def get_formatted_name(first_name,last_name,middle_name=''): """返回全名""" if middle_name: full_name = f"{first_name} {middle_name} {last_name}" else: full_name=f"{first_name} {last_name}" return full_name.title() musician = get_formatted_name('john', 'lee', 'hooker') print(musician) musician = get_formatted_name('jimi', 'hendrix') print(musician)
#
John Hooker Lee
Jimi Hendrix
8. 3. 3 返回字典
#返回字段并有可选项
def build_person(first_name, last_name, age=None): person = {'first': first_name, 'last': last_name} if age: person['age'] = age return person musician = build_person('jimi', 'hendrix') print(musician) musician = build_person('jimi', 'hendrix','28') print(musician)
#
{'first': 'jimi', 'last': 'hendrix'} {'first': 'jimi', 'last': 'hendrix', 'age': '28'}
8. 3. 4 结合使用函数和while 循环
def get_formatted_name(first_name, last_name): """返回整洁的姓名。""" full_name = f"{first_name} {last_name}" return full_name.title() while True: print("\nPlease tell me your name:") 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(f"\nHello, {formatted_name}!")
8. 4 传递列表
def greet_users(names): """向列表中的每位用户发出简单的问候。""" for name in names: msg = f"Hello, {name.title()}!" print(msg) usernames = ['hannah', 'ty', 'margot'] greet_users(usernames) # Hello, Hannah! Hello, Ty! Hello, Margot!
8. 4. 1 在函数中修改列表
#不使用函数之前的代码: # 首先创建一个列表,其中包含一些要打印的设计。 unprinted_designs = ['phone case', 'robot pendant', 'dodecahedron'] completed_models = [] # 模拟打印每个设计,直到没有未打印的设计为止。 # 打印每个设计后,都将其移到列表completed_models中。 while unprinted_designs: current_design = unprinted_designs.pop() print(f"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) print("---------") #使用函数的代码: def print_models(unprinted_designs, completed_models): """模拟打印每个设计,直到没有未打印的设计为止。打印每个设计后,都将其移到列表completed_models中。 """ while unprinted_designs: current_design = unprinted_designs.pop() print(f"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 = ['phone case', 'robot pendant', 'dodecahedron'] completed_models = [] #print_models(unprinted_designs[:], completed_models) #show_completed_models(completed_models) #print(unprinted_designs) print_models(unprinted_designs, completed_models) show_completed_models(completed_models) print(unprinted_designs) #最终unprinted_designs的值会转移到completed_models中
#
Printing model: dodecahedron Printing model: robot pendant Printing model: phone case The following models have been printed: dodecahedron robot pendant phone case --------- Printing model: dodecahedron Printing model: robot pendant Printing model: phone case The following models have been printed: dodecahedron robot pendant phone case []
8. 4. 2 禁止函数修改列表
#要将列表的副本传递给函数,可以像下面这样做:
#function_name(list_name_[:])
#切片表示法[:] 创建列表的副本。在printing_models.py中,如果不想清空未打印 的设计列表,可像下面这样调用print_models() :
#print_models(unprinted_designs[:], completed_models)
#按照上面的写法上一个例子的原列表就不会变成空的了
#print(unprinted_designs)还是有以前的值的
8. 5 传递任意数量的实参
def make_pizza(*toppings): """打印顾客点的所有配料。""" print(toppings) make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese') #('pepperoni',) #('mushrooms', 'green peppers', 'extra cheese') #替换为一个循环,遍历配料列表对顾客描述 def make_pizza(*toppings): """打印顾客点的所有配料。""" for topping in toppings: print(f"- {topping}") make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese') #- pepperoni #- mushrooms #- green peppers
8. 5. 1 结合使用位置实参和任意数量实参
#替换为一个循环,遍历配料列表对顾客描述 def make_pizza(size,*toppings): """打印顾客点的所有配料。""" print(f"\nMaking a {size}-inch pizza with the following toppings:") for topping in toppings: print(f"- {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): """创建一个字典,其中包含我们知道的有关用户的一切。""" user_info['first_name'] = first user_info['last_name'] = last return user_info user_profile = build_profile('albert', 'einstein', location='princeton', field='physics') print(user_profile) print(user_info) # {'location': 'princeton', 'field': 'physics', 'first_name': 'albert', 'last_name': 'einstein'} {'first': 'marie', 'last': 'curie', 'location': 'paris'}
8. 6 将函数存储在模块中
def make_pizza(size, *toppings): """概述要制作的比萨。""" print(f"\nMaking a {size}-inch pizza with the following toppings:") for topping in toppings: print(f"- {topping}")
保存到pizza.py
8. 6. 1 导入整个模块
import pizza pizza.make_pizza(16, 'pepperoni') pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
保存到making_pizzas.py
执行making_pizzas.py
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') # 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. 3 使用as 给函数指定别名
from pizza import make_pizza as mp mp(16, 'pepperoni') mp(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
#指定别名的通用语法如下:
#from module_name import function_name as fn
8. 6. 4 使用as 给模块指定别名
import pizza as p p.make_pizza(16, 'pepperoni') p.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
#给模块指定别名的通用语法如下:
#import module_name as mn
8. 6. 5 导入模块中的所有函数
print("---------") from pizza import * 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
#from module_name import *
九、类
9. 1 创建和使用类
9. 1. 1 创建Dog 类
#首字母大写
class Dog: """一次模拟小狗的简单尝试。""" def __init__(self, name, age): """初始化属性name和age。""" self.name = name self.age = age def sit(self): """模拟小狗收到命令时蹲下。""" print(f"{self.name} is now sitting.") def roll_over(self): """模拟小狗收到命令时打滚。""" print(f"{self.name} rolled over!")
9. 1. 2 根据类创建实例
my_dog = Dog('Willie', 6)
a访问属性
print(f"My dog's name is {my_dog.name}.") print(f"My dog's is {my_dog.age} years old.") # My dog's name is Willie. My dog's is 6 years old.
b调用方法
my_dog.sit() my_dog.roll_over() # Willie is now sitting. Willie rolled over!
c创建多个实例
my_dog = Dog('Willie', 6) your_dog = Dog('Lucy', 3) print(f"My dog's name is {my_dog.name}.") print(f"My dog is {my_dog.age} years old.") my_dog.sit() print(f"\nYour dog's name is {your_dog.name}.") print(f"Your dog is {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 类
print("---------") class Car: """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): """初始化描述汽车的属性。""" self.make = make self.model = model self.year = year def get_descriptive_name(self): """返回整洁的描述性信息。""" long_name = f"{self.year} {self.make} {self.model}" return long_name.title() my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) # 2019 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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): """打印一条指出汽车里程的消息。""" print(f"This car has {self.odometer_reading} miles on it.") my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) my_new_car.read_odometer() # 2019 Audi A4 This car has 0 miles on it.
9. 2. 3 修改属性的值
直接修改
print("---------") my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) my_new_car.odometer_reading = 23 my_new_car.read_odometer() # 2019 Audi A4 This car has 23 miles on it.
通过方法修改属性的值
print("---------") 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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): """打印一条指出汽车里程的消息。""" print(f"This car has {self.odometer_reading} miles on it.") def update_odometer(self,mileage): """将里程表读数设置为指定值""" self.odometer_reading = mileage my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) print("---------") my_new_car.update_odometer(23) my_new_car.read_odometer() # 2019 Audi A4 --------- This car has 23 miles on it.
可以通过方法增加里程数,但是不能减少
print("---------") 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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): """打印一条指出汽车里程的消息。""" print(f"This car has {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!") my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) my_new_car.update_odometer(-1) # 2019 Audi A4 You can't roll back an odometer!
通过方法对属性的值进行递增
print("---------") 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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): """打印一条指出汽车里程的消息。""" print(f"This car has {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 my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) my_new_car.update_odometer(23_500) my_new_car.read_odometer() my_new_car.increment_odometer(100) my_new_car.read_odometer() # 2019 Audi A4 This car has 23500 miles on it. This car has 23600 miles on it.
9. 3 继承
9. 3. 1 子类的方法__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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): print(f"This car has {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) #创建 ElectricCar实例,赋值给变量 my_tesla my_tesla = ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) # 2019 Tesla Model S
9. 3. 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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): print(f"This car has {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 = 75 def describe_battery(self): """打印一条描述电瓶容量的消息。""" print(f"This car has a {self.battery_size}-kWh battery.") my_tesla = ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) my_tesla.describe_battery() # 2019 Tesla Model S This car has a 75-kWh battery.
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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): print(f"This car has {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 #新增方法 def fill_gas_tank(self): print("This car needs a gas tank!") class ElectricCar(Car): """电动汽车的独特之处。""" def __init__(self, make, model, year): """初始化父类的属性。""" super().__init__(make, model, year) #设置初始值 self.battery_size = 75 def describe_battery(self): """打印一条描述电瓶容量的消息。""" print(f"This car has a {self.battery_size}-kWh battery.") #新增方法 def fill_gas_tank(self): """电动汽车没有油箱。""" print("This car doesn't need a gas tank!") my_tesla = ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) my_tesla.fill_gas_tank() # 2019 Tesla Model S This car doesn't need a gas tank!
#重新fill_gas_tank,会忽略父类同名的方法
9. 3. 4 将实例用作属性
#不断给ElectricCar 类添加细节时,我们可能发现其中包含很多专门针对 汽车电瓶的属性和方法。
#在这种情况下,可将这些属性和方法提取出来,放到一个 名为Battery 的类中,
#并将一个Battery 实例作为ElectricCar 类的属性:
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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): print(f"This car has {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=75): """初始化电瓶的属性。""" self.battery_size = battery_size def describe_battery(self): """打印一条描述电瓶容量的消息。""" print(f"This car has a {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', 2019) print(my_tesla.get_descriptive_name()) my_tesla.battery.describe_battery() # 2019 Tesla Model S This car has a 75-kWh battery.
#下面再给Battery 类添加一个方法,它根据电瓶容量 报告汽车的续航里程
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 = f"{self.year} {self.make} {self.model}" return long_name.title() def read_odometer(self): print(f"This car has {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=75): """初始化电瓶的属性。""" self.battery_size = battery_size def describe_battery(self): """打印一条描述电瓶容量的消息。""" print(f"This car has a {self.battery_size}-kWh battery.") def get_range(self): """打印一条消息,指出电瓶的续航里程。""" if self.battery_size == 75: range = 260 elif self.battery_size == 100: range = 315 print(f"This car can go about {range} miles on a full charge.") class ElectricCar(Car): """电动汽车的独特之处。""" def __init__(self, make, model, year): """初始化父类的属性。再初始化电动汽车特有的属性。 """ super().__init__(make, model, year) self.battery = Battery() my_tesla = ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) my_tesla.battery.describe_battery() my_tesla.battery.get_range() my_tesla.battery.battery_size = 100 my_tesla.battery.describe_battery() my_tesla.battery.get_range() # 2019 Tesla Model S This car has a 75-kWh battery. This car can go about 260 miles on a full charge. This car has a 100-kWh battery. This car can go about 315 miles on a full charge.
9. 4 导入类
将类文件保存为my_car.py
需要导入时:
from car import Car
并创建其实例
保存为my_car.py
9. 4. 2 在一个模块中存储多个类
attery 类和ElectricCar 类都可帮助模拟汽车,下面将它们都加 入模块car.py中:
此时car.py包含了Car类,attery类和ElectricCar。
可以新建一个名为my_electric_car.py的文件,导入ElectricCar 类,并 创建一辆电动汽车了:
from car import ElectricCar my_tesla = ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) my_tesla.battery.describe_battery() my_tesla.battery.get_range()
9. 4. 3 从一个模块中导入多个类
from car import Car, ElectricCar
9. 4. 4 导入整个模块
import car
导入模块中的所有类
from module_name import *
不推荐使用这种导入方式,原因有二。
第一,制定类可以清晰知道调用了哪些类将大有裨益。
第二,这种方式还可能引发名称方面的迷惑。
9. 4. 6 在一个模块中导入另一个模块
from car import Car from electric_car import ElectricCar
如果ElectricCar调用了Car,没有导入Car会报错
9. 4. 7 使用别名
from electric_car import ElectricCar as EC my_tesla = EC('tesla', 'roadster', 2019)
十、文件和异常
10.1 从文件中读取数据
with open('pi_digits.txt') as file_object: contents = file_object.read() print(contents.rstrip())
3.1415926535 8979323846 2643383279
10.1.2 文件路径
file_path=('C:\pythonsrc\chapter_10\pi_digits.txt') with open(file_path) as file_object: contents = file_object.read() print(contents.rstrip())
10.1.3 逐行读取
file_path=('C:\pythonsrc\chapter_10\pi_digits.txt') with open(file_path) as file_object: for line in file_object: print(line.rstrip())
10.1.4 创建一个包含文件各行内容的列表
#将每一行存在列表中,在with外对列表进行处理
file_path=('C:\pythonsrc\chapter_10\pi_digits.txt') with open(file_path) as file_object: lines = file_object.readlines() for line in lines: print(line.rstrip())
10.1.5 使用文件的内容
#变成一行
file_path=('C:\pythonsrc\chapter_10\pi_digits.txt') with open(file_path) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.strip() # print(pi_string) print(len(pi_string)) # 3.141592653589793238462643383279 32
10.1.6 包含一百万位的大型文件
#使用切片显示前50位
file_path=('C:\pythonsrc\chapter_10\pi_million_digits.txt') with open(file_path) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.strip() print(pi_string[:52] + "...") print(len(pi_string))
10.1.7 圆周率值中包含你的生日吗
file_path=('C:\pythonsrc\chapter_10\pi_million_digits.txt') with open(file_path) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.strip() 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.") # C:\Users\yangy\AppData\Local\Programs\Python\Python36\python.exe C:/pythonsrc/chapter_10/file_reader.py Enter your birthday, in the form mmddyy: 0326 Your birthday appears in the first million digits of pi! 进程已结束,退出代码 0
10.2 写入文件
10.2.1 写入空文件
filename = 'programming.txt' with open(filename, 'a') as file_object: file_object.write("I love programming.")
#第二个实参('w' )告诉Python,我们要以写入模式 打开这个文件。打开文件 时,可指定读取模式 ('r' )、写入模式 ('w' )、附加模式 ('a' )或让你能够读取和写入文件的模式('r+' )。如果你省略了模式实参,Python将以默认的只读模式打 开文件。
#如果你要写入的文件不存在,函数open() 将自动创建它。然而,以写入('w' )模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空 该文件。
10.2.2 写入多行
filename = '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 异常
#下面来看一种导致Python引发异常的简单错误。你可能知道不能将一个数字除以0,但我们还是让Python这样做吧:
print(5/0) # Traceback (most recent call last): File "C:/pythonsrc/chapter_10/test.py", line 1, in <module> print(5/0) ZeroDivisionError: division by zero 进程已结束,退出代码 1
try: print(5/0) except ZeroDivisionError: print("You can't divide by zero!") # You can't divide by zero!
#我们将导致错误的代码行print(5/0) 放在了一个try 代码块中。如果try 代码块中的代码运行起来没有问题,Python将跳过except 代码块;如果try 代码块中的代码导致了 错误,Python将查找这样的except 代码块,并运行其中的代码,即其中指定的错误与引发的错误相同。
10.3.3 使用异常避免崩溃
#求商,避免用户输入0出现崩溃 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 try: answer = int(first_number) / int(second_number) except ZeroDivisionError: print("You can't divide by 0!") except ValueError: print("please enter a number") else: print(answer) # Give me two numbers, and I'll divide them. Enter 'q' to quit. First number: 7 Second number: 3 2.3333333333333335 First number: 4 Second number: 0 You can't divide by 0! First number: 8 Second number: r please enter a number First number: q 进程已结束,退出代码 0
10.3.5 处理FileNotFoundError 异常
#如果文件不存在 filename = 'alice.txt' with open(filename, encoding='utf-8') as f: contents = f.read() # Traceback (most recent call last): File "C:/pythonsrc/chapter_10/alice.py", line 3, in <module> with open(filename, encoding='utf-8') as f: FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
#这是Python找不到要打开的文件时创建的异常。在这个示例中,这个错误是函数open() 导致的,因此要处理 这个错误,必须将try 语句放在包含open() 的代码行之前:
filename = 'alice.txt' try: with open(filename, encoding='utf-8') as f: contents = f.read() except FileNotFoundError: print(f"Sorry, the file {filename} does not exist.")# Sorry, the file alice.txt does not exist.
10.3.6 分析文本
#split 可以已空格为分隔符进行拆分
filename = 'alice.txt' try: with open(filename, encoding='utf-8') as f: contents = f.read() except FileNotFoundError: print(f"Sorry, the file {filename} does not exist.") else: # Count the approximate number of words in the file. words = contents.split() num_words = len(words) print(f"The file {filename} has about {num_words} words.") # The file alice.txt has about 29465 words.
10.3.7 使用多个文件
们先将这个程序的大部分代码移到一个名为count_words() 的函数中,这样对多本书进行分析时将更容易:
def count_words(filename): """计算一个文件大致包含多少个单词""" try: with open(filename, encoding='utf-8') as f: contents = f.read() except FileNotFoundError: print(f"Sorry, the file {filename} does not exist.") else: # Count the approximate number of words in the file. words = contents.split() num_words = len(words) print(f"The file {filename} has about {num_words} words.") filename = 'alice.txt' count_words(filename)
#
The file alice.txt has about 29465 words.
一个简单的循环,并体现出有文件不存在的情况:
def count_words(filename): """计算一个文件大致包含多少个单词""" try: with open(filename, encoding='utf-8') as f: contents = f.read() except FileNotFoundError: print(f"Sorry, the file {filename} does not exist.") else: # Count the approximate number of words in the file. words = contents.split() num_words = len(words) print(f"The file {filename} has about {num_words} words.") filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt'] for filename in filenames: count_words(filename) # The file alice.txt has about 29465 words. The file siddhartha.txt has about 42172 words. Sorry, the file moby_dick.txt does not exist. The file little_women.txt has about 189079 words.
10.3.8 失败时一声不吭,通过excep决定报告哪些错误
def count_words(filename): """计算一个文件大致包含多少个单词""" try: with open(filename, encoding='utf-8') as f: contents = f.read() except FileNotFoundError: pass else: # Count the approximate number of words in the file. words = contents.split() num_words = len(words) print(f"The file {filename} has about {num_words} words.") filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt'] for filename in filenames: count_words(filename) # The file alice.txt has about 29465 words. The file siddhartha.txt has about 42172 words. The file little_women.txt has about 189079 words.
10.4 存储数据
10.4.1 使用json.dump() 和json.load()
写入:
import json numbers = [2, 3, 5, 7, 11, 13] filename = 'numbers.json' with open(filename, 'w') as f: json.dump(numbers, f) # [2, 3, 5, 7, 11, 13]已经保存到了number.json
读取:
import json filename = 'numbers.json' with open(filename) as f: numbers = json.load(f) print(numbers) # [2, 3, 5, 7, 11, 13]
10.4.2 保存和读取用户生成的数据
#把用户输入的名字保存到username.json文件中
import json username = input("What is your name?") filename = 'username.json' with open(filename, 'w') as f: json.dump(username, f) print(f"We'll remember you when you come back, {username}!") # What is your name?yang We'll remember you when you come back, yang!
已保存到
username.json
再编写一个程序,向其名字被存储的用户发出问候:
import json filename = 'username.json' with open(filename) as f_obj: username = json.load(f_obj) print("Welcome back, " + username + "!")
#
Welcome back, yang!
10.4.3 重构
#我们需要将这两个程序合并到一个程序(remember_me.py)中。这个程序运行时,我们将尝试从文件username.json中获取用户名,因此我们首先编写一个尝试恢复用户名的try 代 码块。如果这个文件不存在,我们就在except 代码块中提示用户输入用户名,并将其存储在username.json中,以便程序再次运行时能够获取它:
import json def get_stored_username(): """Get stored username if available.""" filename = 'username.json' try: with open(filename) as f: username = json.load(f) except FileNotFoundError: return None else: return username def get_new_username(): """Prompt for a new username.""" username = input("What is your name? ") filename = 'username.json' with open(filename, 'w') as f: json.dump(username, f) return username def greet_user(): """Greet the user by name.""" username = get_stored_username() if username: print(f"Welcome back, {username}!") else: username = get_new_username() print(f"We'll remember you when you come back, {username}!") greet_user() # Welcome back, yang!
#在remember_me.py的这个最终版本中,每个函数都执行单一而清晰的任务。我们调用greet_user() ,它打印一条合适的消息:要么欢迎老用户回来,要么问候新用户。为此, 它首先调用get_stored_username() ,这个函数只负责获取存储的用户名(如果存储了的话),再在必要时调用get_new_username() ,这个函数只负责获取并存储新 用户的用户名。要编写出清晰而易于维护和扩展的代码,这种划分工作必不可少。
十一、测试代码
使用Python模块unittest 中的工具来测试代码。
11.1 测试函数
最终name_function.py: # def get_formatted_name(first, last, middle=''): """Generate a neatly formatted full name.""" if middle: full_name = f"{first} {middle} {last}" else: full_name = f"{first} {last}" return full_name.title()
#函数get_formatted_name() 将名和姓合并成姓名,在名和姓之间加上一个空格,并将它们的首字母都大写,再返回结果。
为核实get_formatted_name() 像期望的那样 工作,我们来编写一个使用这个函数的程序。程序names.py让用户输入名和姓,
并显示整洁的全名:
最终names.py: # from name_function import get_formatted_name 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(f"\tNeatly formatted name: {formatted_name}.")
#这个程序从name_function.py中导入get_formatted_name() 。用户可输入一系列的名和姓,并看到格式整洁的全名:
#从上述输出可知,合并得到的姓名正确无误。现在假设我们要修改get_formatted_name() ,使其还能够处理中间名。这样做时,我们要确保不破坏这个函数处理只有名和 姓的姓名的方式。为此,我们可以在每次修改get_formatted_name() 后都进行测试:运行程序names.py,并输入像Janis Joplin 这样的姓名,但这太烦琐了。所幸 Python提供了一种自动测试函数输出的高效方式。倘若我们对get_formatted_name() 进行自动测试,就能始终信心满满,确信给这个函数提供我们测试过的姓名时,它都能 正确地工作。
11.1.1 单元测试和测试用例
Python标准库中的模块unittest 提供了代码测试工具。单元测试 用于核实函数的某个方面没有问题;测试用例 是一组单元测试,这些单元测试一起核实函数在各种情形下的 行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。全覆盖式测试 用例包含一整套单元测试,涵盖了各种可能的函数使用方 式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。
11.1.2 可通过的测试
创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测试就很简单了。要为函数编写测试用例,可先导入模块unittest 以及要测试的函 数,再创建一个继承unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。 下面是一个只包含一个方法的测试用例,它检查函数get_formatted_name() 在给定名和姓时能否正确地工作:
test_name_function.py: # import unittest from name_function import get_formatted_name class NamesTestCase(unittest.TestCase): """测试'name_function.py'.""" def test_first_last_name(self): """Do names like 'Janis Joplin' work?""" formatted_name = get_formatted_name('janis', 'joplin') self.assertEqual(formatted_name, 'Janis Joplin') def test_first_last_middle_name(self): """Do names like 'Wolfgang Amadeus Mozart' work?""" formatted_name = get_formatted_name( 'wolfgang', 'mozart', 'amadeus') self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart') if __name__ == '__main__': unittest.main()
#
Ran 2 tests in 0.000s
OK
Launching unittests with arguments python -m unittest C:/pythonsrc/chapter_11/test_name_function.py in C:\pythonsrc\chapter_11
11.1.3 不能通过的测试
修改name_function.py: # def get_formatted_name(first, last, middle=''): """Generate a neatly formatted full name.""" if middle: full_name = f"{first} {middle} {last}" return full_name.title()
这次运行程序test_name_function.py时:
Ran 2 tests in 0.003s
FAILED (errors=1)
Launching unittests with arguments python -m unittest test_name_function.NamesTestCase in C:\pythonsrc\chapter_11
Error
Traceback (most recent call last):
File "C:\Users\yangy\AppData\Local\Programs\Python\Python36\lib\unittest\case.py", line 59, in testPartExecutor
yield
File "C:\Users\yangy\AppData\Local\Programs\Python\Python36\lib\unittest\case.py", line 605, in run
testMethod()
File "C:\pythonsrc\chapter_11\test_name_function.py", line 10, in test_first_last_name
formatted_name = get_formatted_name('janis', 'joplin')
File "C:\pythonsrc\chapter_11\name_function.py", line 5, in get_formatted_name
return full_name.title()
UnboundLocalError: local variable 'full_name' referenced before assignment
进程已结束,退出代码 1
断言失败
断言失败
断言失败
11.1.4 测试未通过时怎么办
name_function.py: # def get_formatted_name(first, last, middle=''): """生成整洁的姓名""" if middle: full_name = f"{first} {middle} {last}" else: full_name = f"{first} {last}" return full_name.title()
#
Launching unittests with arguments python -m unittest C:/pythonsrc/chapter_11/test_name_function.py in C:\pythonsrc\chapter_11 Ran 2 tests in 0.002s OK
11.1.5 添加新测试
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') def test_first_last_middle_name(self): """能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?""" formatted_name = get_formatted_name( 'wolfgang', 'mozart', 'amadeus') self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart') if __name__ == '__main__': unittest.main() # Launching unittests with arguments python -m unittest C:/pythonsrc/chapter_11/test_name_function.py in C:\pythonsrc\chapter_11 Ran 2 tests in 0.002s OK
11.2 测试类
11.2.1 各种断言方法
方法 | 用途 |
assertEqual(a, b) | 核实a == b |
assertNotEqual(a, b) | 核实a != b |
assertTrue(x) | 核实x 为True |
assertFalse(x) | 核实x 为False |
assertIn(item , list ) | 核实 item 在 list 中 |
assertNotIn(item , list ) | 核实 item 不在 list 中 |
11. 2. 2 一个要测试的类
survey.py:
class AnonymousSurvey: """收集匿名调查问卷的答案。""" def __init__(self, question): """存储一个问题,并为存储答案做准备。""" self.question = question self.responses = [] def show_question(self): """显示调查问卷。""" print(self.question) def store_response(self, new_response): """存储单份调查答卷。""" self.responses.append(new_response) def show_results(self): """显示收集到的所有答卷。""" print("Survey results:") for response in self.responses: print(f"- {response}")
language_survey.py:
from survey import AnonymousSurvey # 定义一个问题,并创建一个调查。 question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question) # 显示问题并存储答案。 my_survey.show_question() print("Enter 'q' at any time to quit.\n") while True: response = input("Language: ") if response == 'q': break my_survey.store_response(response) # 显示调查结果。 print("\nThank you to everyone who participated in the survey!") my_survey.show_results()
11. 2. 3 测试AnonymousSurvey 类
test_survey.py:
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(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) if __name__ == '__main__': unittest.main()
#
Launching unittests with arguments python -m unittest C:/pythonsrc/chapter_11/test_survey.py in C:\pythonsrc\chapter_11
Ran 1 test in 0.002s
OK
进程已结束,退出代码 0
#测试一个答案
#继续测试三个不同的答案:
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(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) def test_store_three_responses(self): """测试三个答案会被妥善地存储。""" question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question) responses = ['English', 'Spanish', 'Mandarin'] for response in responses: my_survey.store_response(response) for response in responses: self.assertIn(response, my_survey.responses) if __name__ == '__main__': unittest.main() # Launching unittests with arguments python -m unittest C:/pythonsrc/chapter_11/test_survey.py in C:\pythonsrc\chapter_11 Ran 2 tests in 0.002s OK 进程已结束,退出代码 0
11. 2. 4 方法setUp()
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """针对AnonymousSurvey类的测试。""" def setUp(self): """创建一个调查对象和一组答案,供使用的测试方法使用。 """ question = "What language did you first learn to speak?" self.my_survey = AnonymousSurvey(question) self.responses = ['English', 'Spanish', 'Mandarin'] def test_store_single_response(self): """测试单个答案会被妥善地存储。""" self.my_survey.store_response(self.responses[0]) self.assertIn(self.responses[0], self.my_survey.responses) def test_store_three_responses(self): """测试三个答案会被妥善地存储。""" for response in self.responses: self.my_survey.store_response(response) for response in self.responses: self.assertIn(response, self.my_survey.responses) if __name__ == '__main__': unittest.main() # Launching unittests with arguments python -m unittest C:/pythonsrc/chapter_11/test_survey.py in C:\pythonsrc\chapter_11 Ran 2 tests in 0.001s OK 进程已结束,退出代码 0
搭建编程环境