本书编写期间的最新版本为Python 3.7,但只要你安装了Python 3.6或更高的版本,就能运行本书中的所有代码。
运行Python代码片段
C:\> python --version
Python 3.7.0
C:\> python
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> print("Hello Python interpreter!")
Hello Python interpreter!
>>>
文件名和文件夹名称最好使用小写字母,并使用下划线代替空格,因为Python采用了这些命名约定。
Windows 系统使用命令dir(表示directory,即目录)可以显示当前目录中的所有文件。
从终端运行Python程序
C:\> cd Desktop\python_work
C:\Desktop\python_work> dir
hello_world.py
C:\Desktop\python_work> python hello_world.py
Hello Python world!
message = "Hello Python world!"
print(message)
message = "Hello Python Crash Course world!"
print(message)
变量名称错误通常意味着两种情况:要么是使用变量前忘记给它赋值,要么是输 入变量名时拼写不正确。
变量是可以赋给值的标签,也可以说变量指向特定的值。
在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。这种灵活性让你能够在字符串中包含引号和撇号:
'I told my friend, "Python is my favorite language!"'
"The language 'Python' is named after Monty Python, not the snake." "One of Python's strengths is its diverse and supportive community."
name = "ada lovelace"
print(name.title()) // Ada Lovelace
print(name.upper()) // ADA LOVELACE
print(name.lower()) // ada lovelace
first_name = "ada"
last_name = "lovelace"
full_name = f"{first_name} {last_name}" print(full_name)
first_name = "ada" last_name = "lovelace"
full_name = f"{first_name} {last_name}"
print(f"Hello, {full_name.title()}!")
full_name = "{} {}".format(first_name, last_name)
>>> print("Python")
Python
>>> print("\tPython")
Python
>>> print("Languages:\nPython\nC\nJavaScript")
Languages:
Python
C
JavaScript
>>> favorite_language = 'python '
>>> favorite_language
'python '
>>> favorite_language.rstrip()
'python'
>>> favorite_language
'python '
>>> favorite_language = 'python '
>>> favorite_language = favorite_language.rstrip()
>>> favorite_language
'python'
>>> favorite_language = ' python '
>>> favorite_language.rstrip()
' python'
>>> favorite_language.lstrip()
'python '
>>> favorite_language.strip()
'python'
>>> 0.2 + 0.1
0.30000000000000004
>>> 3 * 0.1
0.30000000000000004
>>> 4/2
2.0
>>> 1 + 2.0
3.0
>>> 2 * 3.0
6.0
>>> 3.0 ** 2
9.0
>>> universe_age = 14_000_000_000
>>> print(universe_age)
14000000000
>>> x, y, z = 0, 0, 0
MAX_CONNECTIONS = 5000
在Python中,注释用井号(#)标识。井号后面的内容都会被Python解释器忽略。
要获悉有关编写优秀Python代码的指导原则,只需在解释器中执行命令import this。
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)
['trek', 'cannondale', 'redline', 'specialized']
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0])
print(bicycles[0].title())
trek
Trek
在Python中,第一个列表元素的索引为0,而不是1。
Python为访问最后一个列表元素提供了一种特殊语法。通过将索引指定为-1,可让Python返回最后一个列表元素。这种约定也适用于其他负数索引。例如,索引-2返回倒数第二个列表元素,索引-3返回倒数第三个列表元素,依此类推。
要修改列表元素,可指定列表名和要修改的元素的索引,再指定该元素的新值。
motorcycles[0] = 'ducati'
1. 在列表末尾添加元素
motorcycles = [] // 创建一个空列表
motorcycles.append('ducati')
2. 在列表中插入元素
motorcycles.insert(0, 'ducati')
1. 使用del语句删除元素
del motorcycles[0]
2. 使用方法pop()删除元素
popped_motorcycle = motorcycles.pop()
3. 弹出列表中任何位置处的元素
first_owned = motorcycles.pop(0)
4. 根据值删除元素
motorcycles.remove('ducati')
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort()
print(cars)
cars.sort(reverse=True)
print(sorted(cars))
cars.reverse()
>>> cars = ['bmw', 'audi', 'toyota', 'subaru']
>>> len(cars)
4
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)
print(f"I can't wait to see your next trick, {magician.title()}.\n")
Python根据缩进来判断代码行与前一个代码行的关系。如果你不小心缩进了无须缩进的代码行,Python将指出这一点。
for语句末尾的冒号告诉Python,下一行是循环的第一行。如果不小心遗漏了冒号,将导致语法错误。
列表非常适合用于存储数字集合,而Python提供了很多工具,可帮助你高效地处理数字列表。
Python函数range()让你能够轻松地生成一系列数。
for value in range(1, 5):
print(value)
1
2
3
4
numbers = list(range(1, 6))
print(numbers) // [1, 2, 3, 4, 5]
// 在这个示例中,函数range()从2开始数,然后不断加2,直到达到或超过终值
even_numbers = list(range(2, 11, 2))
print(even_numbers) // [2, 4, 6, 8, 10]
// 创建一个列表,其中包含前10个整数(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]
>>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> min(digits)
0
>>> max(digits)
9
>>> sum(digits)
45
squares = [value**2 for value in range(1, 11)]
print(squares) // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3]) // ['charles', 'martina', 'michael']
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[:4]) // ['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']
for player in players[:3]:
print(player.title())
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
friend_foods.append('ice cream')
# 这行不通:
friend_foods = my_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')
print(my_foods) // ['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']
列表非常适合用于存储在程序运行期间可能变化的数据集。
Python将不能修改的值称为不可变的,而不可变的列表被称为元组。
元组看起来很像列表,但使用圆括号而非中括号来标识。定义元组后,就可使用索引来访问其元素,就像访问列表元素一样。
dimensions = (200, 50)
print(dimensions[0])
print(dimensions[1])
my_t = (3,)
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)
dimensions = (200, 50)
print("Original dimensions:")
for dimension in dimensions:
print(dimension)
dimensions = (400, 100)
print("\nModified dimensions:")
for dimension in dimensions:
print(dimension)
如果需要存储的一组值在程序的整个生命周期内都不变,就可以使用元组。
要提出Python语言修改建议,需要编写Python改进提案(Python Enhancement Proposal,PEP)。PEP 8是最古老的PEP之一,向Python程序员提供了代码格式设置指南。
每条if语句的核心都是一个值为True或False的表达式,这种表达式称为条件测试。Python根据条件测试的值为True还是False来决定是否执行if语句中的代码。如果条件测试的值为True,Python就执行紧跟在if语句后面的代码;如果为False,Python就忽略这些代码。
最简单的条件测试检查变量的值是否与特定值相等。
>>> car == 'bmw'
True
>>> car = 'Audi'
>>> car == 'audi'
False
>>> car = 'Audi'
>>> car.lower() == 'audi'
True
>>> car
'Audi'
requested_topping = 'mushrooms'
if requested_topping != 'anchovies':
print("Hold the anchovies!")
>>> age = 18
>>> age == 18
True
>>> age = 19
>>> age < 21
True
>>> age <= 21
True
>>> age > 21
False
>>> age >= 21
False
>>> age_0 = 22
>>> age_1 = 18
>>> age_0 >= 21 and age_1 >= 21 // 或 (age_0 >= 21) and (age_1 >= 21)
False
>>> age_0 = 22
>>> age_1 = 18
>>> age_0 >= 21 or age_1 >= 21
True
>>> requested_toppings = ['mushrooms', 'onions', 'pineapple']
>>> 'mushrooms' in requested_toppings
True
banned_users = ['andrew', 'carolina', 'david']
user = 'marie'
if user not in banned_users:
print(f"{user.title()}, you can post a response if you wish.")
game_active = True
can_edit = False
age = 19
if age >= 18:
print("You are old enough to vote!")
print("Have you registered to vote yet?")
当需要在条件测试通过时执行一个操作,在没有通过时执行另一个操作,可使用Python提供的if-else语句。
我们经常需要检查超过两个的情形,为此可使用Python提供的if-elif-else结构。Python只执行if-elif-else结构中的一个代码块。它依次检查每个条件测试,直到遇到通过了的条件测试。
// 例子1:
age = 12
if age < 4:
print("Your admission cost is $0.")
elif age < 18:
print("Your admission cost is $25.")
else:
print("Your admission cost is $40.")
// 例子2:
age = 12
if age < 4:
price = 0
elif age < 18:
price = 25
else:
price = 40
print(f"Your admission cost is ${price}.")
可根据需要使用任意数量的elif代码块。
Python并不要求if-elif结构后面必须有else代码块。在有些情况下,else代码块很有用;而在其他一些情况下,使用一条elif语句来处理特定的情形更清晰。
age = 12
if age < 4:
price = 0
elif age < 18:
price = 25
elif age < 65:
price = 40
elif age >= 65:
price = 20
print(f"Your admission cost is ${price}.")
如果只想执行一个代码块,就使用if-elif-else结构;如果要执行多个代码块,就使用一系列独立的if语句。
在运行for循环前确定列表是否为空很重要。
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?")
alien_0 = {'color': 'green', 'points': 5}
print(alien_0['color']) // green
print(alien_0['points']) // 5
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)
alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0) // {'color': 'green', 'points': 5, 'x_position': 0, 'y_position': 25}
alien_0 = {}
alien_0['color'] = 'green'
alien_0['points'] = 5
alien_0 = {'color': 'green'}
alien_0['color'] = 'yellow'
alien_0 = {'color': 'green', 'points': 5}
del alien_0['points']
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
alien_0 = {'color': 'green', 'speed': 'slow'}
point_value = alien_0.get('points', 'No point value assigned.')
print(point_value)
字典可用于以各种方式存储信息,因此有多种遍历方式:可遍历字典的所有键值对,也可仅遍历键或值。
使用for循环来遍历字典
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}
for key, value in user_0.items():
print(f"\nKey: {key}")
print(f"Value: {value}")
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in favorite_languages.keys():
print(name.title())
for name in favorite_languages:
替换为:for name in favorite_languages.keys():
输出将不变。显式地使用方法keys()可让代码更容易理解,你可以选择这样做,但是也可以省略它。favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
if 'erin' not in favorite_languages.keys():
print("Erin, please take our poll!")
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in sorted(favorite_languages.keys()):
print(f"{name.title()}, thank you for taking the poll.")
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for language in favorite_languages.values():
print(language.title())
for language in set(favorite_languages.values()):
print(language.title())
>>> languages = {'python', 'ruby', 'python', 'c'}
>>> languages
{'ruby', 'python', 'c'}
// 例子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)
// 例子2:
# 创建一个用于存储外星人的空列表。
aliens = []
# 创建30个绿色的外星人。
for alien_number in range(30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)
# 显示前5个外星人。
for alien in aliens[:5]:
print(alien)
print("...")
# 显示创建了多少个外星人。
print(f"Total number of aliens: {len(aliens)}")
# 存储所点比萨的信息。
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"\t{topping}")
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']}"
location = user_info['location']
print(f"\tFull name: {full_name.title()}")
print(f"\tLocation: {location.title()}")
message = input("Tell me something, and I will repeat it back to you: ")
print(message)
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(f"\nHello, {name}!")
>>> age = input("How old are you? ")
How old are you? 21
>>> age = int(age)
>>> age >= 18
True
number = input("Enter a number, and I'll tell you if it's even or odd: ")
number = int(number)
if number % 2 == 0:
print(f"\nThe number {number} is even.")
else:
print(f"\nThe number {number} is odd.")
for循环用于针对集合中的每个元素都执行一个代码块,而while循环则不断运行,直到指定的条件不满足为止。
可使用while循环来数数。
current_number = 1
while current_number <= 5:
print(current_number)
current_number += 1
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)
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)
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()}!")
current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
continue
print(current_number)
如果程序陷入无限循环,可按Ctrl + C,也可关闭显示程序输出的终端窗口。注意,Sublime Text等一些编辑器内嵌了输出窗口,这可能导致难以结束无限循环,不得不通过关闭编辑器来结束。在这种情况下,可在输出窗口中单击鼠标,再按Ctrl + C,这样应该能够结束无限循环。
for循环是一种遍历列表的有效方式,但不应在for循环中修改列表,否则将导致Python难以跟踪其中的元素。要在遍历列表的同时对其进行修改,可使用while循环。
在列表之间移动元素
# 首先,创建一个待验证用户列表
# 和一个用于存储已验证用户的空列表。
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []
# 验证每个用户,直到没有未验证用户为止。
# 将每个经过验证的用户都移到已验证用户列表中。
while unconfirmed_users:
current_user = unconfirmed_users.pop()
print(f"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())
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)
while 'cat' in pets:
pets.remove('cat')
print(pets)
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}.")
def greet_user():
"""显示简单的问候语。""" // A处
print("Hello!")
greet_user()
def greet_user(username):
"""显示简单的问候语。"""
print(f"Hello, {username.title()}!")
greet_user('jesse')
向函数传递实参的方式很多:可使用位置实参,这要求实参的顺序与形参的顺序相同;也可使用关键字实参,其中每个实参都由变量名和值组成;还可使用列表和字典。
调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式称为位置实参。
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')
describe_pet('dog', 'willie')
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')
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')
describe_pet('willie')
// 等效的函数调用
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')
describe_pet('harry', 'hamster')
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) // Jimi Hendrix
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('jimi', 'hendrix')
print(musician)
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)
// 例子1:
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'}
// 例子2:
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', age=27)
print(musician)
def greet_users(names):
"""向列表中的每位用户发出简单的问候。"""
for name in names:
msg = f"Hello, {name.title()}!"
print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
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)
function_name(list_name_[:])
例如 unprinted_designs 需要传递副本:
print_models(unprinted_designs[:], completed_models)
def make_pizza(*toppings):
"""打印顾客点的所有配料。"""
print(toppings)
make_pizza('pepperoni') // ('pepperoni',)
make_pizza('mushrooms', 'green peppers', 'extra cheese') // ('mushrooms', 'green peppers', 'extra cheese')
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')
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) // {'location': 'princeton', 'field': 'physics', 'first_name': 'albert', 'last_name': 'einstein'}
// pizza.py 文件
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所在的目录中创建一个名为making_pizzas.py的文件。这个文件导入刚创建的模块,再调用make_pizza() 两次:
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
def function_name(parameter_0, parameter_1='default value')
function_name(value_0, parameter_1='value')
def function_name(
parameter_0, parameter_1, parameter_2,
parameter_3, parameter_4, parameter_5):
function body...
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!")
my_dog = Dog('Willie', 6) // A处
print(f"My dog's name is {my_dog.name}.") // B处
print(f"My dog is {my_dog.age} years old.")
my_dog.sit()
my_dog.roll_over()
class Car:
def init (self, make, model, year):
"""初始化描述汽车的属性。"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
1、直接修改属性的值
my_new_car.odometer_reading = 23
2、通过方法修改属性的值
class Car:
...
def update_odometer(self, mileage):
"""将里程表读数设置为指定的值。"""
self.odometer_reading = mileage
my_new_car.update_odometer(23)
3、通过方法对属性的值进行递增
class Car:
...
def increment_odometer(self, miles):
"""将里程表读数增加指定的量。"""
self.odometer_reading += miles
my_used_car.increment_odometer(100)
编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。
在既有类的基础上编写新类时,通常要调用父类的方法__init__()。这将初始化在父类__init__()方法中定义的所有属性,从而让子类包含这些属性。
class Car:
"""一次模拟汽车的简单尝试。"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
class ElectricCar(Car):
"""电动汽车的独特之处。"""
def __init__(self, make, model, year):
"""
初始化父类的属性。
再初始化电动汽车特有的属性。
"""
super().__init__(make, model, year)
self.battery_size = 75
class ElectricCar(Car):
--snip--
def fill_gas_tank(self):
"""电动汽车没有油箱。"""
print("This car doesn't need a gas tank!")
class Battery:
"""一次模拟电动汽车电瓶的简单尝试。"""
def __init__(self, battery_size=75):
"""初始化电瓶的属性。"""
self.battery_size = battery_size
class ElectricCar(Car):
"""电动汽车的独特之处。"""
def __init__(self, make, model, year):
"""
初始化父类的属性。
再初始化电动汽车特有的属性。
"""
super().__init__(make, model, year)
self.battery = Battery()
Python允许将类存储在模块中,然后在主程序中导入所需的模块。
导入单个类
// car.py 文件
"""一个可用于表示汽车的类。"""
class Car:
"""一次模拟汽车的简单尝试。"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性。"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
...
// my_car.py 文件
from car import Car
my_new_car = Car('audi', 'a4', 2019)
// car.py 文件
"""一组用于表示燃油汽车和电动汽车的类。"""
class Car:
--snip--
class Battery:
"""一次模拟电动汽车电瓶的简单尝试。"""
def __init__(self, battery_size=75):
"""初始化电瓶的属性。"""
self.battery_size = battery_size
class ElectricCar(Car):
"""模拟电动汽车的独特之处。"""
def __init__(self, make, model, year):
"""
初始化父类的属性。
再初始化电动汽车特有的属性。
"""
super().__init__(make, model, year)
self.battery = Battery()
// my_electric_car.py 文件
from car import ElectricCar
my_tesla = ElectricCar('tesla', 'model s', 2019)
from car import Car, ElectricCar
import car
my_beetle = car.Car('volkswagen', 'beetle', 2019)
print(my_beetle.get_descriptive_name())
my_tesla = car.ElectricCar('tesla', 'roadster', 2019)
print(my_tesla.get_descriptive_name())
from module_name import *
// car.py 文件
"""一个可用于表示汽车的类。"""
class Car:
--snip--
// electric_car.py 文件
"""一组可用于表示电动汽车的类。"""
from car import Car
class Battery:
--snip--
class ElectricCar(Car):
--snip--
// 在 import 语句中给 ElectricCar 指定一个别名:
from electric_car import ElectricCar as EC
my_tesla = EC('tesla', 'roadster', 2019)
>>> from random import randint
>>> randint(1, 6)
3
>>> from random import choice
>>> players = ['charles', 'martina', 'michael', 'florence', 'eli']
>>> first_up = choice(players)
>>> first_up
'florence'
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents.rstrip())
with open('text_files/filename.txt') as file_object:
file_path = '/home/ehmatthes/other_files/text_files/_filename_.txt'
with open(file_path) as file_object:
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line)
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
3.1415926535
8979323846
2643383279
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
pi_string = ''
for line in lines:
pi_string += line.strip() // 删除每行末尾的换行符和原来位于每行左边的空格
print(pi_string)
print(len(pi_string))
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
filename = '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")
如果要给文件添加内容,而不是覆盖原有的内容,可以以附加模式打开文件。以附加模式打开文件时,Python不会在返回文件对象前清空文件的内容,而是将写入文件的行添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。
Python使用称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行;如果未对异常进行处理,程序将停止并显示traceback,其中包含有关异常的报告。
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
--snip--
while True:
--snip--
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)
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.")
>>> title = "Alice in Wonderland"
>>> title.split()
['Alice', 'in', 'Wonderland']
12.要让程序静默失败,可像通常那样编写try代码块,但在except代码块中明确地告诉Python什么都不要做。Python有一个pass语句,可用于让Python在代码块中什么都不要做。
def count_words(filename):
"""计算一个文件大致包含多少个单词。"""
try:
--snip--
except FileNotFoundError:
pass
else:
--snip--
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]
import json
filename = 'numbers.json'
with open(filename) as f:
numbers = json.load(f)
print(numbers) // [2, 3, 5, 7, 11, 13]
import json
# 如果以前存储了用户名,就加载它。
# 否则,提示用户输入用户名并存储它。
filename = 'username.json'
try:
with open(filename) as f:
username = json.load(f)
except FileNotFoundError:
username = input("What is your name? ")
with open(filename, 'w') as f:
json.dump(username, f) # 文件内容为:"xxx"
print(f"We'll remember you when you come back, {username}!")
else:
print(f"Welcome back, {username}!")
import json
def get_stored_username():
"""如果存储了用户名,就获取它。"""
filename = 'username.json'
try:
with open(filename) as f:
username = json.load(f)
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:
json.dump(username, f)
return username
def greet_user():
"""问候用户,并指出其名字。"""
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()
Python标准库中的模块unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题。测试用例是一组单元测试,它们一道核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。全覆盖的测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。
要为函数编写测试用例,可先导入模块unittest和要测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。
// 要测试的函数,在 name_function.py 文件中
def get_formatted_name(first, last):
"""生成整洁的姓名。"""
full_name = f"{first} {last}"
return full_name.title()
// 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):
"""能够正确地处理像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__': // A处
unittest.main()
// 运行结果如下:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
方法 | 用途 |
---|---|
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 中 |
// 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}")
// 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)
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()
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()
第 12 章至第 20 章为项目部分,略。