本附录包含每章末尾练习题的答案。我强烈建议你花时间解决这些问题。编程不仅仅是记住语法和一系列函数名。就像学习一门外语一样,你投入的练习越多,收获就越多。也有很多网站有练习编程的问题。你可以在/nostarch.com/automatestuff2
的找到这些的列表。
当谈到实践项目时,没有一个正确的程序。只要你的程序执行了项目所要求的,你就可以认为它是正确的。然而,如果你想看已完成项目的例子,可以在的“下载书中使用的文件”链接中找到。
第一章
- 运算符有
+
、-
、*
和/
。这些值是'hello'
、-88.8
和5
。 - 变量是
spam
;字符串是'spam'
。字符串总是以引号开始和结束。 - 本章介绍的三种数据类型是整数、浮点数和字符串。
- 表达式是值和运算符的组合。所有表达式都计算(即归约)为一个值。
- 表达式计算为单个值。语句不会。
bacon
变量被设置为20
。bacon + 1
表达式不重新分配bacon
中的值(那需要一个赋值语句:bacon = bacon + 1
)。- 两个表达式的计算结果都是字符串
'spamspamspam'
。 - 变量名不能以数字开头。
int()
、float()
和str(
函数将计算传递给它们的值的整数、浮点数和字符串版本。- 该表达式会导致错误,因为
99
是一个整数,只有字符串可以用+
运算符连接到其他字符串。正确的做法是I have eaten ' + str(99) + ' burritos.'
。
第二章
True
和False
,用大写的T
和F
,其余的单词用小写and
、or
和not
True and True
就是True
。True and False
就是False
。False and True
就是False
。False and False
就是False
。True or True
就是True
。True or False
就是True
。False or True
就是True
。False or False
就是False
。not True
就是False
。not False
就是True
。False
False
True
False
False
True
==``!=``<``>``<=``>=
==
是比较两个值并计算出布尔值的等于运算符,而=
是将值存储在变量中的赋值运算符。- 条件是在流程控制语句中使用的表达式,其计算结果为布尔值。
- 这三个块是
if
语句和行print('bacon')
和print('ham')
中的所有内容。
print('eggs') if spam > 5: print('bacon') else: print('ham') print('spam')
- 代码:
if spam == 1: print('Hello') elif spam == 2: print('Howdy') else: print('Greetings!')
- 按下
CTRL-C
停止陷入无限循环的程序。 break
语句将把执行移到一个循环之外,就在一个循环之后。continue
语句将把执行移到循环的开始。- 他们都做同样的事情。
range(10)
调用范围从0
到(但不包括)10
,range(0, 10)
显式地告诉循环从0
开始,range(0, 10, 1)
显式地告诉循环在每次迭代中增加变量1
。 - 代码:
for i in range(1, 11): print(i)
- 以及:
i = 1 while i <= 10: print(i) i = i + 1
- 这个函数可以用
spam.bacon()
调用。
第三章
- 函数减少了对重复代码的需求。这使得程序更短,更容易阅读,更容易更新。
- 函数中的代码在调用函数时执行,而不是在定义函数时执行。
def
语句定义(即创建)一个函数。- 函数由
def
语句及其def
子句中的代码组成。函数调用是将程序执行转移到函数中,函数调用计算函数的返回值。 - 有一个全局作用域,每当调用一个函数时就会创建一个局部作用域。
- 当函数返回时,局部作用域被破坏,其中的所有变量都被遗忘。
- 返回值是函数调用计算得出的值。像任何值一样,返回值可以用作表达式的一部分。
- 如果一个函数没有返回语句,那么它的返回值就是
None
。 - 一个
global
语句将强制函数中的一个变量引用全局变量。 None
的数据类型为NoneType
。- 那个
import
语句导入了一个名为areallyourpetsnamederic
的模块。(顺便说一下,这不是真正的 Python 模块。) - 这个函数可以用
spam.bacon()
调用。 - 将可能导致错误的代码行放在
try
子句中。 - 可能导致错误的代码放在
try
子句中。发生错误时执行的代码放在except
子句中。
第四章
- 空列表值,即不包含任何项目的列表值。这类似于
''
是空字符串值。 spam[2] = 'hello'
(注意,列表中的第三个值位于索引2
,因为第一个索引是0
。)'d'
(注意'3' * 2
是字符串'33'
,在被11
除之前传递给int()
。这最终求值为3
。只要使用值,就可以使用表达式。)'d'
(负数索引从末尾算起。)['a', 'b']
1
[3.14, 'cat', 11, 'cat', True, 99]
[3.14, 11, 'cat', True]
- 列表连接的操作符是
+
,而复制的操作符是*
。(这与字符串相同。) - 虽然
append()
只会将值添加到列表的末尾,但是insert()
可以将它们添加到列表中的任何位置。 del
语句和remove()
列表方法是从列表中删除值的两种方法。- 列表和字符串都可以传递给
len()
,有索引和切片,可以在for
循环中使用,可以连接或复制,可以与in
和not in
操作符一起使用。 - 列表是可变的;它们可以添加、删除或更改值。元组是不可变的;它们根本无法改变。同样,元组使用圆括号、
(
和)
编写,而列表使用方括号、[
和]
。 (42,)
(尾部逗号是强制的。)- 分别是
tuple()
和list()
函数 - 它们包含对列表值的引用。
copy.copy()
函数将做一个列表的浅层拷贝,而copy.deepcopy()
函数将做一个列表的深层拷贝。也就是说,只有copy.deepcopy()
会复制列表中的任何列表。
第五章
- 两个花括号:
{}
{'foo': 42}
- 存储在字典中的条目是无序的,而列表中的条目是有序的。
- 您会得到一个
KeyError
错误。 - 没有区别。
in
操作符检查一个值是否作为一个键存在于字典中。 'cat' in spam
检查字典中是否有一个'cat'
键,而'cat' in spam.values()
检查spam
中是否有一个键的值'cat'
。spam.setdefault('color', 'black')
pprint.pprint()
第六章
- 转义字符表示字符串值中的字符,否则很难或不可能键入代码中。
\n
是换行符;\t
是一个制表符。\\
转义字符将代表反斜杠字符。- 在
Howl's
中的单引号很好,因为你已经用双引号标记了字符串的开始和结束。 - 多行字符串允许您在不带
\n
转义字符的字符串中使用换行符。 - 这些表达式的计算结果如下:
'e'
'Hello'
'Hello'
'lo, world!
- 这些表达式的计算结果如下:
'HELLO'
True
'hello'
- 这些表达式的计算结果如下:
['Remember,', 'remember,', 'the', 'fifth', 'of', 'November.']
'There-can-be-only-one.'
- 分别是
rjust()
、ljust()
和center()
字符串方法 lstrip()
和rstrip()
方法分别从字符串的左端和右端删除空白。
第七章
re.compile()
函数返回Regex
对象。- 使用原始字符串是为了避免对反斜杠进行转义。
search()
方法返回Match
对象。group()
方法返回匹配文本的字符串。- 组
0
是整个匹配,组1
包含第一组括号,组2
包含第二组括号。 - 句点和括号可以用反斜杠进行转义:
\.
、\(
和\)
。 - 如果正则表达式没有组,则返回字符串列表。如果正则表达式有组,则返回字符串元组的列表。
|
字符表示两个组之间的“非此即彼”匹配。?
字符可以表示“匹配零个或前面组中的一个”,也可以用来表示非贪婪匹配。+
匹配一个或多个。*
匹配零个或更多。{3}
恰好匹配前一组的三个实例。{3,5}
匹配三到五个实例。\d
、\w
和\s
速记字符类分别匹配单个数字、单词或空格字符。\D
、\W
和\S
速记字符类分别匹配不是数字、单词或空格字符的单个字符。.*
执行贪婪匹配,.*?
执行非贪婪匹配。[0-9a-z]
或[a-z0-9]
- 将
re.I
或re.IGNORECASE
作为第二个参数传递给re.compile()
会使匹配不区分大小写。 .
字符通常匹配除换行符之外的任何字符。如果re.DOTALL
作为第二个参数传递给re.compile()
,那么点号也将匹配换行符。- 调用
sub()
将返回字符串'X drummers, X pipers, five rings, X hens'
。 re.VERBOSE
参数允许您向传递给re.compile()
的字符串添加空白和注释。re.compile(r'^\d{1,3}(,\d{3})*$')
将创建这个正则表达式,但是其他正则表达式字符串可以产生一个类似的正则表达式。re.compile(r'[A-Z][a-z]*\sWatanabe')
re.compile(r'(Alice|Bob|Carol)\s(eats|pets|throws)\s(apples|cats|baseballs)\.', re.IGNORECASE)
第八章
- 不可以。PyInputPlus 是第三方模块,不附带 Python 标准库。
- 这可以使你的代码更短:你可以输入
pyip.inputStr()
而不是pyinputplus.inputStr()
。 inputInt()
函数返回一个 int 值,而inputFloat()
函数返回一个 float 值。这就是返回4
和4.0
的区别。- 调用
pyip.inputint(min=0, max=99)
。 - 明确允许或拒绝的正则表达式字符串列表
- 该函数将引发
RetryLimitException
。 - 该函数返回值
'hello'
。
第九章
- 相对路径是相对于当前工作目录的。
- 绝对路径以根文件夹开始,比如
/
或者C:\
。 - 在 Windows 上,它计算为
WindowsPath('C:/Users/Al')
。在其他操作系统上,它求值为不同种类的Path
对象,但是具有相同的路径。 - 表达式
'C:/Users' / 'Al'
会导致错误,因为您不能使用/
操作符来连接两个字符串。 os.getcwd()
函数返回当前工作目录。os.chdir()
函数改变当前工作目录。.
文件夹是当前文件夹,..
是父文件夹。C:\bacon\eggs
是目录名,而spam.txt
是基本名。- 字符串
'r'
表示读取模式,'w'
表示写入模式,'a'
表示附加模式 - 以写入模式打开的现有文件将被擦除并完全覆盖。
read()
方法将文件的全部内容作为一个字符串值返回。readlines()
方法返回一个字符串列表,其中每个字符串都是文件内容中的一行。- 架子值类似于字典值;它有键和值,以及类似于同名字典方法的
keys()
和values()
方法。
第十章
shutil.copy()
函数将复制单个文件,而shutil.copytree()
将复制整个文件夹及其所有内容。shutil.move()
函数用于重命名和移动文件。send2trash
函数将文件或文件夹移动到回收站,而shutil
函数将永久删除文件和文件夹。zipfile.ZipFile()
函数等同于open()
函数;第一个参数是文件名,第二个参数是打开 ZIP 文件的模式(读、写或附加)。
第十一章
assert spam >= 10, 'The spam variable is less than 10.'
assert eggs.lower() != bacon.lower() 'The eggs and bacon variables are the same!'
或assert eggs.upper() != bacon.upper(), 'The eggs and bacon variables are the same!'
assert False, 'This assertion always triggers.'
- 为了能够调用
logging.debug()
,在程序的开始必须有这两行代码:
import logging logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
- 为了能够用
logging.debug()
将日志消息发送到一个名为programLog.txt
的文件中,在程序的开始必须有这两行:
import logging >>> logging.basicConfig(filename='programLog.txt', level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
- 调试、信息、警告、错误和严重
logging.disable(logging.CRITICAL)
- 您可以在不删除日志记录函数调用的情况下禁用日志记录消息。您可以有选择地禁用低级别的日志消息。您可以创建日志消息。记录消息提供了时间戳。
- “单步执行”按钮会将调试器移动到函数调用中。“单步执行”按钮将快速执行函数调用,而无需单步执行。“跳出”按钮将快速执行剩余的代码,直到它跳出当前所在的函数。
- 单击“继续”后,调试器将在到达程序结尾或带有断点的一行时停止。
- 断点是一行代码上的设置,当程序执行到该行时,它会导致调试器暂停。
- 要在 Mu 中设置断点,请单击行号,使其旁边出现一个红点。
第十二章
webbrowser
模块有一个open()
方法,它将启动一个 Web 浏览器到一个特定的 URL,就是这样。requests
模块可以从网上下载文件和网页。BeautifulSoup
模块解析 HTML。最后,selenium
模块可以启动和控制浏览器。requests.get()
函数返回一个Response
对象,该对象具有一个text
属性,该属性以字符串形式包含下载的内容。- 如果下载有问题,
raise_for_status()
方法会引发一个异常,如果下载成功则不做任何事情。 Response
对象的status_code
属性包含 HTTP 状态代码。- 在你的计算机上以
'wb'
“写二进制”模式打开新文件后,使用一个for
循环迭代Response
对象的iter_content()
方法,将块写出到文件中。这里有一个例子:
saveFile = open('filename.html', 'wb') for chunk in res.iter_content(100000): saveFile.write(chunk)
F12
在 Chrome 中调出开发者工具。按下CTRL-SHIFT-C
(在 Windows 和 Linux 上)或Cmd-OPTION-C
(在 OS X 上)调出 Firefox 中的开发者工具。- 右键单击页面中的元素,从菜单中选择 检查元素。
'#main'
'.highlight'
'div div'
'button[value="favorite"]'
spam.getText()
linkElem.attrs
selenium
模块用from selenium import webdriver
导入。find_element_*
方法返回第一个匹配元素作为一个WebElement
对象。find_elements_*
方法返回所有匹配元素的列表作为WebElement
对象。click()
和send_keys()
方法分别模拟鼠标点击和键盘按键。- 对表单中的任何元素调用
submit()
方法都会提交表单。 forward()
、back()
和refresh()
对象方法模拟这些浏览器按钮。
第十三章
openpyxl.load_workbook()
函数返回一个Workbook
对象。sheetnames
属性包含一个Worksheet
对象。- 运行
wb['Sheet1']
。 - 使用
wb.active
。 sheet['C5'].value
或sheet.cell(row=5, column=3).value
sheet['C5'] = 'Hello'
或sheet.cell(row=5, column=3).value = 'Hello'
cell.row
和cell.column
- 它们分别将工作表中最高的列和行的值保存为整数值。
openpyxl.cell.column_index_from_string('M')
openpyxl.cell.get_column_letter(14)
sheet['A1':'F1']
wb.save('example.xlsx')
- 公式的设置方式与任何值相同。将单元格的
value
属性设置为公式文本的字符串。请记住,公式以=符号开始。 - 调用
load_workbook()
时,为data_only
关键字参数传递True
。 sheet.row_dimensions[5].height = 100
sheet.column_dimensions['C'].hidden = True
- 冻结窗格是总是出现在屏幕上的行和列。它们对标题很有用。
openpyxl.chart.Reference()
、openpyxl.chart.Series()
、openpyxl.chart.BarChart()
、chartObj.append(seriesObj)
和add_chart()
第十四章
- 要访问谷歌表格,您需要一个证书文件、一个谷歌表格的令牌文件和一个谷歌网盘的令牌文件。
- EZSheets 有
ezsheets.Spreadsheet
和ezsheets.Sheet
对象。 - 调用
downloadAsExcel()
Spreadsheet
方法。 - 调用
ezsheets.upload()
函数并传递 Excel 文件的文件名。 - 访问
ss['Students']['B2']
。 - 调用
ezsheets.getColumnLetterOf(999)
。 - 访问
Sheet
对象的rowCount
和columnCount
属性。 - 调用
delete()
Sheet
方法。只有当你传递了permanent=True
关键字参数,这才是永久的。 createSpreadsheet()
函数和createSheet()
Spreadsheet
方法将分别创建Spreadsheet
和Sheet
对象。- EZSheets 将抑制您的方法调用。
第十五章
- 从
open()
返回的File
对象 PdfFileReader()
读二进制('rb'
)和PdfFileWriter()
写二进制('wb'
- 调用
getPage(4)
将为第 5 页返回一个Page
对象,因为第 0 页是第一页。 numPages
变量存储了PdfFileReader
对象中页数的整数。- 调用
decrypt('swordfish')
。 rotateClockwise()
和rotateCounterClockwise()
方法。要旋转的度数作为整数参数传递。docx.Document('demo.docx')
- 一个文档包含多个段落。段落从新行开始,包含多个段落。游程是段落中连续的字符组。
- 使用
doc.paragraphs
。 Run
对象有这些变量(不是段落)。True
总是使Run
对象加粗,False
总是不加粗,不管样式的加粗设置是什么。None
将使Run
对象只使用样式的加粗设置。- 调用
docx.Document()
函数。 doc.add_paragraph('Hello there!')
- 整数
0
、1
、2
、3
和4
第十六章
- 在 Excel 中,电子表格可以有字符串以外的数据类型的值;单元格可以有不同的字体、大小或颜色设置。单元格可以有不同的宽度和高度;相邻单元格可以合并;你可以嵌入图片和图表。
- 您传递一个从对
open()
的调用中获得的File
对象。 - 对于
reader
对象,需要以读二进制('rb'
)打开对象,对于writer
对象,需要以写二进制('wb'
)打开对象。 writerow()
方法delimiter
参数改变用于分隔一行中单元格的字符串。lineterminator
参数改变用于分隔行的字符串。json.loads()
json.dumps()
第十七章
- 许多日期和时间程序使用的参考时刻。此刻是世界协调时 1970 年 1 月 1 日。
time.time()
time.sleep(5)
- 它返回与传递的参数最接近的整数。例如,
round(2.4)
返回2
。 - 一个
datetime
物体代表一个特定的时刻。一个timedelta
对象代表一段时间。 - 运行
datetime.datetime(2019, 1, 7).weekday()
,返回0
。这意味着周一,因为datetime
模块使用0
表示周一,1
表示周二,依此类推,直到6
表示周日。 threadObj = threading.Thread(target=spam) threadObj.start()
- 确保在一个线程中运行的代码不会读取或写入与在另一个线程中运行的代码相同的变量。
第十八章
- 分别是 SMTP 和 IMAP
smtplib.SMTP()
、smtpObj.ehlo()
、smptObj.starttls()
和smtpObj.login()
imapclient.IMAPClient()
和imapObj.login()
- IMAP 关键字的字符串列表,如
'BEFORE <date>'
、'FROM <string>'
或'SEEN'
- 给变量
imaplib._MAXLINE
赋一个大的整数值,比如10000000
。 pyzmail
模块读取下载的电子邮件。credentials.json
和token.json
文件告诉 EZGmail 模块在访问 Gmail 时使用哪个谷歌账户。- 一条消息代表一封邮件,而涉及多封邮件的来回对话就是一个线程。
- 在传递给
search()
的字符串中包含'has:attachment'
文本。 - 您将需要 Twilio 帐户 SID 号、认证令牌号和您的 Twilio 电话号码。
第十九章
- RGBA 值是一个由 4 个整数组成的元组,每个整数的范围从 0 到 255。这四个整数对应于颜色中红色、绿色、蓝色和 alpha(透明度)的数量。
- 对
ImageColor.getcolor('CornflowerBlue', 'RGBA')
的函数调用将返回该颜色的 RGBA 值(100, 149, 237, 255)
。 - 盒子元组是四个整数的元组值:左边的 x 坐标、上边的 y 坐标、宽度和高度。
Image.open('zophie.png')
imageObj.size
是两个整数的元组,宽度和高度。imageObj.crop((0, 50, 50, 50))
。注意,您传递给crop()
的是一个盒子元组,而不是四个独立的整数参数。- 调用
Image
对象的imageObj.save('new_filename.png')
方法。 - 模块包含了在图像上绘图的代码。
ImageDraw
物体有point()
、line()
或rectangle()
等形状绘制方法。它们通过将Image
对象传递给ImageDraw.Draw()
函数来返回。
第二十章
- 将鼠标移动到屏幕的左上角,即
(0, 0)
坐标。 pyautogui.size()
返回一个包含两个整数的元组,表示屏幕的宽度和高度。pyautogui.position()
返回一个带有两个整数的元组,代表鼠标光标的 x 和 y 坐标。moveTo()
函数将鼠标移动到屏幕上的绝对坐标,而move()
函数相对于鼠标的当前位置移动鼠标。pyautogui.dragTo()
和pyautogui.drag()
pyautogui.typewrite('Hello, world!')
- 要么将一列键盘按键串传递给
pyautogui.write()
(比如'left'
),要么将一个单独的键盘按键串传递给pyautogui.press()
。 pyautogui.screenshot('screenshot.png')
pyautogui.PAUSE = 2
- 您应该使用 Selenium 来控制 Web 浏览器,而不是 PyAutoGUI。
- PyAutoGUI 盲目地点击和输入,不容易发现它是否点击和输入了正确的窗口。意外的弹出窗口或错误会使脚本偏离轨道,并要求您将其关闭。
- 调用
pyautogui.getWindowsWithTitle('Notepad')
函数。 - 运行
w = pyatuogui.getWindowsWithTitle('Firefox')
,然后运行w.activate()
。