9.md 20.2 KB
Newer Older
W
wizardforcel 已提交
1
# 九、加强您的 Python 基础
W
wizardforcel 已提交
2 3 4

这些章节随附的代码示例不需要您精通 Python。 但是,他们将假定您之前至少已经掌握了 Python 脚本编写的基础知识。 他们还将特别假设您了解数据结构(例如列表和字典),并且对如何使类对象起作用具有想法。

W
wizardforcel 已提交
5
如果您对上述主题没有信心或对 Python 语言了解甚少,建议您在开始阅读本书之前,先参加在线教程,例如[这个页面](http://www.codecademy.com/en/tracks/python),位于[这个页面](https://developers.google.com/edu/python/)的 Google Python 课程或 [Kaggle 提供的课程](https://www.kaggle.com/learn/python)。 所有课程都是免费的,并且在几个小时的学习中,它们应该为您提供所有基础知识,以确保您充分享受这本书。 如果您喜欢在一本书中学习 Python 基础知识,则可以阅读 [Jake Vanderplas](https://github.com/jakevdp/WhirlwindTourOfPython) 的《Python 旋风之旅》,您需要的 Python 基本知识:从变量赋值到导入包。 我们还准备了一些注释,这些注释在本简短但具有挑战性的奖金一章中进行了介绍,以突出显示重要性和增强您对 Python 语言对数据科学使用至关重要的所有方面的知识。 在本章中,您将学到以下内容:
W
wizardforcel 已提交
6 7 8 9 10 11

*   关于成为有效数据科学家的 Python 知识
*   通过观看视频学习 Python 的最佳资源
*   通过直接编写和测试代码来学习 Python 的最佳资源
*   通过阅读学习 Python 的最佳资源

W
wizardforcel 已提交
12
# 您的学习列表
W
wizardforcel 已提交
13 14 15

这是您需要学习像数据科学家一样熟练的基本 Python 数据结构。 除了实际的基础知识(数字,算术,字符串,布尔值,变量赋值和比较)之外,列表确实很短。 我们将通过仅涉及数据科学项目中的递归结构来简要地处理它。 请记住,这些主题颇具挑战性,但是如果您想编写有效的代码,则必须掌握这些主题:

W
wizardforcel 已提交
16
*   列表
W
wizardforcel 已提交
17
*   字典
W
wizardforcel 已提交
18
*   类,对象和面向对象的编程
W
wizardforcel 已提交
19
*   异常
W
wizardforcel 已提交
20
*   迭代器和生成器
W
wizardforcel 已提交
21 22 23
*   条件
*   推导式
*   函数
W
wizardforcel 已提交
24

W
wizardforcel 已提交
25
根据您对 Python 语言的实际了解,将其作为复习或学习列表。 但是,请检查所有建议的示例,因为在本书学习过程中您将再次遇到它们。
W
wizardforcel 已提交
26

W
wizardforcel 已提交
27
# 列表
W
wizardforcel 已提交
28

W
wizardforcel 已提交
29
列表是元素的集合。 元素可以是整数,浮点数,字符串或一般对象。 此外,您可以将不同的类型混合在一起。 此外,列表比数组更灵活,因为数组仅允许单个数据类型。 要创建列表,可以使用方括号或`list()`构造器,如下所示:
W
wizardforcel 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

```py
a_list = [1, 2.3, 'a', True]
an_empty_list = list()
```

以下是一些在使用列表时需要记住的便捷方法:

*   要访问第<sup></sup>元素,请使用`[]`表示法:

请记住,列表从 0(零)开始索引; 也就是说,第一个元素的位置为 0。

```py
a_list[1] 
# prints 2.3 
a_list[1] = 2.5
# a_list is now [1, 2.5, 'a', True]
```

*   您可以通过指出起点和终点(所得终点中不包括终点)来对列表进行切片,如下所示:

```py
a_list[1:3]
# prints [2.3, 'a']
```

*   您可以使用冒号分隔的`start:end:skip`表示法对跳过进行切片,以便为每个跳过值获取一个元素,如下所示:

```py
a_list[::2] 
# returns only odd elements: [1, 'a'] a_list[::-1] 
# returns the reverse of the list: [True, 'a', 2.3, 1]
```

*   要在列表末尾添加元素,可以使用`append()`

```py
a_list.append(5) 
# a_list is now [1, 2.5, 'a', True, 5]
```

*   要获取列表的长度,请使用`len()`函数,如下所示:

```py
len(a_list) 
# prints 5
```

*   要删除元素,请使用`del`语句,后跟要删除的元素:

```py
del a_list[0] 
# a_list is now [2.5, 'a', True, 5]
```

W
wizardforcel 已提交
85
*   要连接两个列表,请使用`+`,如下所示:
W
wizardforcel 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

```py
a_list += [1, 'b'] 
# a_list is now [2.5, 'a', True, 5, 1, 'b']
```

*   您可以通过将列表分配给变量列表(或只是序列)而不是单个变量来解压缩列表:

```py
a, b, c, d, e, f = [2.5, 'a', True, 5, 1, 'b'] 
# a now is 2.5, b is 'a' and so on
```

请记住,列表是可变的数据结构; 您可以随时添加,删除和修改元素。 不可变列表称为元组,并用圆括号`(``)`表示,而不是列表`[``]`中的方括号:

```py
tuple(a_list) 
# prints (2.5, 'a', True, 5, 1, 'b')
```

W
wizardforcel 已提交
106
# 字典
W
wizardforcel 已提交
107

W
wizardforcel 已提交
108
**词典**是可以快速查找内容的表,因为每个键都与一个值相关联。 确实就像使用书的索引立即跳到您需要的内容。 键和值可以属于不同的数据类型。 键的唯一先决条件是它们应该是可散列的(这是一个相当复杂的概念;只需使键尽可能简单,因此,请勿尝试使用字典或列表作为键)。 要创建字典,可以使用大括号,如下所示:
W
wizardforcel 已提交
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

```py
b_dict = {1: 1, '2': '2', 3.0: 3.0}
```

以下是使用字典时可以记住的一些便捷方法:

*   要访问通过`k`键索引的值,请使用`[]`表示法,如下所示:

```py
b_dict['2'] 
# prints '2' 
b_dict['2'] = '2.0' 
# b_dict is now {1: 1, '2': '2.0', 3.0: 3.0}
```

*   要插入或替换键的值,请再次使用`[]`表示法:

```py
b_dict['a'] = 'a' 
# b_dict is now {3.0: 3.0, 1: 1, '2': '2.0', 'a': 'a'}
```

*   要获取字典中的元素数,请使用`len()`函数,如下所示:

```py
len(b_dict) 
# prints 4
```

*   要删除元素,请使用`del`语句,后跟要删除的元素:

```py
del b_dict[3.0] 
# b_dict is now {1: 1, '2': '2.0', 'a': 'a'}
```

请记住,字典(如列表)是可变的数据结构。 还要记住,如果您尝试访问其键不存在的元素,则会引发`KeyError`异常:

```py
b_dict['a_key'] 

Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'a_key'
```

显而易见的解决方案是始终先检查字典中是否有元素:

```py
if 'a_key' in b_dict: 
 b_dict['a_key'] 
else: 
 print("'a_key' is not present in the dictionary")
```

否则,您可以使用`.get`方法。 如果键在字典中,则返回其值; 否则,不返回任何内容:

```py
b_dict.get('a_key')
```

W
wizardforcel 已提交
169
最后,您可以使用集合模块中的数据结构`defaultdict`,它将永远不会引发`KeyError`,因为它是由不带任何参数,并为它可能想要的任何不存在的键提供默认值的函数实例化的:
W
wizardforcel 已提交
170 171 172 173 174 175 176 177

```py
from collections import defaultdict 
c_dict = defaultdict(lambda: 'empty') 
c_dict['a_key'] 
# requiring a nonexistent key will always return the string 'empty'
```

W
wizardforcel 已提交
178
可以使用`def``lambda`命令定义`defaultdict`使用的`default`函数,如下节所述。
W
wizardforcel 已提交
179

W
wizardforcel 已提交
180
# 定义函数
W
wizardforcel 已提交
181

W
wizardforcel 已提交
182
函数是指令的集合,通常会从您那里接收特定的输入,并提供与这些输入相关的一组特定的输出。 您可以将它们定义为单线,如下所示:
W
wizardforcel 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

```py
def half(x): 
    return x/2.0
```

您还可以通过以下方式将它们定义为一组许多指令:

```py
import math 
def sigmoid(x): 
    try: 
        return 1.0 / (1 + math.exp(-x)) 
    except: 
        if x < 0: 
             return 0.0 
        else: 
             return 1.0
```

W
wizardforcel 已提交
203
最后,您可以使用`lambda`函数来创建匿名函数。 将匿名函数视为简单函数,您可以在代码中的任何位置内联定义,而无需使用`verbose`构造器(以`def`开头的函数)。 只需调用`lambda`,然后输入其输入参数即可; 然后,冒号将发信号通知要由`lambda`函数执行的命令的开始,这些命令必须在同一行上。 (没有`return`命令!这些命令将从`lambda`函数返回。)您可以将`lambda`函数用作另一个函数的参数,如先前在`defaultdict`中看到的那样,也可以使用它在一行中表达一个函数。 在我们的示例中就是这种情况,我们通过返回`lambda`函数并结合第一个参数来定义函数:
W
wizardforcel 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

```py
def sum_a_const(c): 
return lambda x: x+c 

sum_2 = sum_a_const(2) 
sum_3 = sum_a_const(3) 
print(sum_2(2)) 
print(sum_3(2)) 
# prints 4 and 5
```

要调用一个函数,请写上函数名称,然后在括号内写上其参数:

```py
half(10) 
# prints 5.0 
sigmoid(0) 
# prints 0.5
```

通过使用函数,您可以通过对重复过程进行形式化的输入和输出来使重复过程组合在一起,而不会让它们的计算以任何方式干扰主程序的执行。 实际上,除非您声明变量是全局变量,否则将丢弃您在函数中使用的所有变量,并且主程序将仅接收`return`命令返回的内容。

W
wizardforcel 已提交
227
顺便说一句,请注意,如果您将一个列表传递给一个仅函数的列表,而该列表不会在变量中发生,那么即使不返回,也将对其进行修改,除非您将其复制。 为了复制列表,您可以使用复制或深层复制功能(要从复制包中导入),也可以仅使用应用于列表的运算符`[:]`
W
wizardforcel 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

为什么会这样? 因为列表尤其是由地址而不是整个对象引用的数据结构。 因此,当您将列表传递给函数时,您只是将一个地址传递给计算机的内存,该函数将通过修改您的实际列表来对该地址进行操作:

```py
a_list = [1,2,3,4,5] 

def modifier(L): 
L[0] = 0 

def unmodifier(L): 
    M = L[:] # Here we are copying the list
 M[0] = 0 

unmodifier(a_list) 
print(a_list) 
# you still have the original list, [1, 2, 3, 4, 5] 

modifier(a_list) 
print(a_list) 
# your list have been modified: [0, 2, 3, 4, 5]
```

# 类,对象和面向对象的编程

类是方法和属性的集合。 简而言之,属性是对象的变量(例如,`Employee`类的每个实例都有其自己的`name``age``salary``benefits`;它们都是属性)。

方法只是修改属性的简单函数(例如,设置员工姓名,设置他/她的年龄以及从数据库或 CSV 列表中读取此信息)。 要创建一个类,请使用`class`关键字。

在下面的示例中,我们将为增量器创建一个类。 此对象的目的是跟踪整数值,并最终将其增加 1:

```py
class Incrementer(object): 
 def __init__(self): 
 print ("Hello world, I'm the constructor") 
 self._i = 0
```

`def`缩进中的所有内容都是`class`方法。 在这种情况下,名为`__init__`的方法会将`i`内部变量设置为零(它看起来就像上一章中描述的函数一样)。 仔细查看方法的定义。 它的参数是`self`(这是对象本身),每个内部变量的访问都通过`self`进行:

W
wizardforcel 已提交
267
1.  `__init__`不仅仅是一种方法; 它是构造器(在创建对象时调用)。 实际上,当我们构建`Increment`对象时,将自动调用此方法,如下所示:
W
wizardforcel 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327

```py
i = Incrementer() 
# prints "Hello world, I'm the constructor"
```

2.  现在,让我们创建`increment()`方法,该方法将增加`i`内部计数器并返回状态。 在类定义中,包括方法:

```py
def increment(self): 
 self._i += 1 
 return self._i
```

3.  然后,运行以下代码:

```py
i = Incrementer() 
print (i.increment()) 
print (i.increment()) 
print (i.increment())
```

4.  上面的代码产生以下输出:

```py
Hello world, I'm the constructor 
1 
2 
3
```

最后,让我们看看如何创建接受参数的方法。 现在,我们将创建`set_counter`方法,该方法设置`_i`内部变量:

1.  在类定义中,添加以下代码:

```py
def set_counter(self, counter): 
 self._i = counter
```

2.  然后,运行以下代码:

```py
i = Incrementer() 
i.set_counter(10) 
print (i.increment()) 
print (i._i)
```

3.  上面的代码给出以下输出:

```py
Hello world, I'm the constructor 
11 
11
```

请注意前面代码的最后一行,您可以在其中访问内部变量。 请记住,在 Python 中,默认情况下对象的所有内部属性都是公共的,并且可以在外部读取,写入和更改它们。

W
wizardforcel 已提交
328
# 异常
W
wizardforcel 已提交
329

W
wizardforcel 已提交
330
异常和错误密切相关,但是它们是不同的东西。 例如,可以很好地处理异常。 以下是一些异常示例:
W
wizardforcel 已提交
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354

```py
0/0 

Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: integer division or modulo by zero 

len(1, 2) 

Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: len() takes exactly one argument (2 given) 

pi * 2 

Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'pi' is not defined
```

在此示例中,提出了三个不同的异常(请参见每个块的最后一行)。 要处理异常,可以通过以下方式使用`try...except`块:

```py
try: 
 a = 10/0 
except ZeroDivisionError: 
 a = 0
```

W
wizardforcel 已提交
355
您可以使用一个以上的`except`子句来处理多个异常。 您最终可以使用最终的`all-the-other`异常处理器。 在这种情况下,结构如下:
W
wizardforcel 已提交
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418

```py
try: 
 <code which can raise more than one exception> 
except KeyError: 
 print ("There is a KeyError error in the code") 
except (TypeError, ZeroDivisionError): 
 print ("There is a TypeError or a ZeroDivisionError error in the code") except: 
 print ("There is another error in the code")
```

最后,重要的是要提到有最后一个子句`finally`,它将在所有情况下执行。 如果您要清理代码(关闭文件,取消分配资源等),这非常方便。 这些都是应该独立完成的事情,无论是否发生错误。 在这种情况下,代码采用以下形状:

```py
try: 
 <code that can raise exceptions> 
except: 
 <eventually more handlers for different exceptions> 
finally: 
 <clean-up code>
```

# 迭代器和生成器

遍历列表或字典非常简单。 请注意,对于字典而言,迭代是基于键的,下面的示例对此进行了演示:

```py
for entry in ['alpha', 'bravo', 'charlie', 'delta']: 
 print (entry) 

# prints the content of the list, one entry for line 

a_dict = {1: 'alpha', 2: 'bravo', 3: 'charlie', 4: 'delta'} 
for key in a_dict: 
 print (key, a_dict[key]) 

# Prints: 
# 1 alpha 
# 2 bravo 
# 3 charlie 
# 4 delta
```

另一方面,如果您需要遍历序列并快速生成对象,则可以使用生成器。 这样做的一个很大好处是,您不必在一开始就创建和存储完整的序列。 取而代之的是,每次调用生成器时,都会构建每个对象。 作为一个简单的示例,让我们为数字序列创建一个生成器,而无需事先存储完整列表:

```py
def incrementer(): 
 i = 0 
 while i<5: 
 yield(i)
 i +=1 

for i in incrementer(): 
 print (i) 

# Prints: 
# 0 
# 1 
# 2 
# 3 
# 4
```

W
wizardforcel 已提交
419
# 条件
W
wizardforcel 已提交
420

W
wizardforcel 已提交
421
因为您可以分支程序,所以条件常用于数据科学中。 最常用的是`if`语句。 它的工作原理与其他编程语言大致相同。 这是一个例子:
W
wizardforcel 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445

```py
def is_positive(val): 
 if val< 0: 
 print ("It is negative") 
 elif val> 0: 
 print ("It is positive") 
 else: 
 print ("It is exactly zero!") 

is_positive(-1) 
is_positive(1.5) 
is_positive(0) 

# Prints: 
# It is negative 
# It is positive 
# It is exactly zero!
```

`if`检查第一个条件。 如果还有其他条件,则用`elif`定义(代表`else...if`)。 最后,默认行为由`else`处理。

注意,`elif``else`不是必需的。

W
wizardforcel 已提交
446
# 列表和字典的推导式
W
wizardforcel 已提交
447

W
wizardforcel 已提交
448
使用通过迭代器和条件构建为一行的推导式,列表和字典:
W
wizardforcel 已提交
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469

```py
a_list = [1,2,3,4,5] 
a_power_list = [value**2 for value in a_list] 
# the resulting list is [1, 4, 9, 16, 25] 

filter_even_numbers = [value**2 for value in a_list if value % 2 == 0] 
# the resulting list is [4, 16] 

```

```py
another_list = ['a','b','c','d','e'] 
a_dictionary = {key:value for value, key in zip(a_list, another_list)} 
# the resulting dictionary is {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
```

`zip`是一个函数,该函数将多个相同长度的列表作为输入,并同时遍历具有相同索引的每个元素,因此您可以将每个列表的前几个元素匹配在一起,依此类推。

理解是过滤和转换迭代器中存在的数据的快速方法。

W
wizardforcel 已提交
470
# 通过观看,阅读和实践来学习
W
wizardforcel 已提交
471 472 473 474 475

如果进修课程和我们的学习列表还不够,您需要更多支持以增强您的 Python 知识怎么办? 我们将建议您在网上免费获得更多资源。 通过观看教程视频,您可以尝试复杂且不同的示例,并通过一项艰巨的任务挑战自己,该任务需要您与其他数据科学家和 Python 专家进行互动。

# 大规模公开在线课程(MOOC)

W
wizardforcel 已提交
476
近年来,MOOC 变得越来越流行,在其在线平台上免费提供来自世界各地最好的大学和专家的一些最好的课程。 您将在 [Coursera](https://www.coursera.org/)[Edx](https://www.edx.org/)[Udacity](https://www.udacity.com)。 另一个很好的来源是 MIT 开放式课件,[它很容易访问](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00sc-introduction-to-computer-science-and-programming-spring-2011/)
W
wizardforcel 已提交
477 478 479 480 481

当您访问这些站点中的每一个时,您可能会发现有关 Python 的其他有效课程。 我们建议 Google Inc.研究总监 Peter Norvig 提供免费的,始终可用的,自己动手的进度课程。该课程旨在使您对 Python 的了解达到更高的水平。

# PyCon 和 PyData

W
wizardforcel 已提交
482
**Python 大会****PyCon**)是在世界各地举办的年度大会,旨在促进 Python 语言的使用和传播。 在此类会议期间,通常会举行教程,动手演示和培训课程。 您可以查看[这个页面](http://www.pycon.org/),了解在您附近举行下一次 PyCon 的地点和时间。 如果您无法参加,则仍然可以在[这个页面](http://www.youtube.com)上进行搜索,因为大多数有趣的会话均已记录并上传到那里。 无论如何,参加和观看真实的演示是另一回事,所以我们热烈建议您参加这样的会议,因为这确实值得。
W
wizardforcel 已提交
483

W
wizardforcel 已提交
484
类似地,**PyData** 是致力于数据分析的 Python 开发人员和用户社区,在世界各地组织了许多活动。 您可以查看[这个页面](http://pydata.org/events.html)即将发生的事件,并查看是否有任何以往的事件对您感兴趣。 与 PyCon 一样,通常可以在 YouTube 上的 PyDataTV 等专用频道上进行演示。
W
wizardforcel 已提交
485 486 487 488 489

# 交互式 Jupyter

有时,您需要一些书面说明,并有机会自己测试一些示例代码。 Jupyter 是一个类似 Python 本身的开放工具,可通过其笔记本(交互式网页)为您提供所有这些功能,您可以在其中找到说明和可以直接测试的示例代码。 我们在整本书中都对 Jupyter 及其内核进行了说明,因为它是真正的数据科学。 它使您可以轻松地运行 Python 脚本,并评估它们对正在处理的数据的影响。

W
wizardforcel 已提交
490
IPython 内核(Jupyter 的 Python 内核,因为 Jupyter 可以运行许多不同的编程语言)的 GitHub 位置提供了示例笔记本的完整列表。 您可以在[这个页面](https://github.com/ipython/ipython/wiki/A-gallery-of-interesting-IPython-Notebooks)上进行检查。 特别是,列表的一部分与**通用 Python 编程**有关,而另一部分与**统计,机器学习和数据科学**有关,您会在其中找到很多 Python 脚本的示例,您可以从中学到灵感。
W
wizardforcel 已提交
491 492 493

# 别害羞,接受真正的挑战

W
wizardforcel 已提交
494
如果您想做一些可以使您的 Python 编码能力达到不同水平的事情,我们建议您去挑战 Kaggle。 [**Kaggle**](http://www.kaggle.com) 是用于预测建模和分析竞赛的平台,在数据中应用了竞争性编程(参与者尝试根据提供的规范进行编程)的思想,向参与者提出具有挑战性的数据问题,并要求他们提供可能在测试集上评估的解决方案,从而实现科学。 测试集的结果部分是公开的,部分是私有的。
W
wizardforcel 已提交
495

W
wizardforcel 已提交
496
对于 Python 学习者来说,最有趣的部分是有机会参加没有明显解决方案的实际问题,这需要您编写一些代码以提出可能的问题解决方案,甚至是简单或幼稚的解决方案(我们建议您从头开始) 参与复杂的解决方案之前)。 这样,学习者将发现有趣的教程,基准测试代码,有用的数据科学家社区,以及其他数据科学家或 [Kaggle](http://blog.kaggle.com/) 本身在其博客中提出的一些非常聪明的解决方案。 
W
wizardforcel 已提交
497

W
wizardforcel 已提交
498
您可能想知道如何为自己找到正确的挑战。 只需在[这个页面](https://www.kaggle.com/competitions)上查看过去和现在的比赛,并寻找每一个有知识作为奖励的比赛。 您会惊讶地发现一个理想的阶段来学习其他数据科学家如何用 Python 进行编码,并且您可以立即应用从本书中学到的知识。