Skip to content

Commit 931d7fc

Browse files
committed
typo
1 parent 574afed commit 931d7fc

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

2.5.md

+20-21
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ True
164164

165165
## 2.5.3 消息传递和点表达式
166166

167-
方法定义在类中,而实例属性通常在狗在其中赋值,二者都是面向对象编程的基本元素。这两个概念很大程序上类似于数据值的消息传递实现中的分发字典。对象使用点运算符接受消息,但是消息并不是任意的字符串的键,而是类局部的名称。对象也拥有具名的局部状态值(实例属性),但是这个状态可以使用点运算符访问和操作,并不需要在实现中使用`nonlocal`语句。
167+
方法定义在类中,而实例属性通常在构造器中赋值,二者都是面向对象编程的基本元素。这两个概念很大程度上类似于数据值的消息传递实现中的分发字典。对象使用点运算符接受消息,但是消息并不是任意的、值为字符串的键,而是类的局部名称。对象也拥有具名的局部状态值(实例属性),但是这个状态可以使用点运算符访问和操作,并不需要在实现中使用`nonlocal`语句。
168168

169-
消息传递的核心概念,就是数据值应该通过响应消息而拥有行为,这些消息和它们所表示的抽象类型相关。点运算符是 Python 的语法特征,它形成了消息传递的隐喻。使用带有内建对象系统语言的优点是,消息传递能够和其它语言特征无缝对接,就像赋值语句那样。我们并不需要不同的消息来“获取”和“设置”关联到局部属性名称的值;语言的语法允许我们直接使用消息名称。
169+
消息传递的核心概念,就是数据值应该通过响应消息而拥有行为,这些消息和它们所表示的抽象类型相关。点运算符是 Python 的语法特征,它形成了消息传递的隐喻。使用带有内建对象系统语言的优点是,消息传递能够和其它语言特性,例如赋值语句无缝对接。我们并不需要不同的消息来“获取”和“设置”关联到局部属性名称的值;语言的语法允许我们直接使用消息名称。
170170

171-
**点表达式。**`tom_account.deposit`的代码片段叫做点表达式。点表达式包含一个表达式,一个点和一个名称:
171+
**点表达式。**类似`tom_account.deposit`的代码片段叫做点表达式。点表达式包含一个表达式,一个点和一个名称:
172172

173173
```
174174
<expression> . <name>
@@ -192,9 +192,9 @@ True
192192

193193
对象的属性包含所有实例属性,以及所有定义在类中的属性(包括方法)。方法是需要特别处理的类的属性。
194194

195-
**方法和函数。**当一个方法在对象上调用时,对象隐式地作为第一个参数传递给方法。也就是说,点运算符左边值为`<expression>`的对象是会自动传给点运算符右边的方法,作为第一个参数。所以,对象绑定到了参数`self`上。
195+
**方法和函数。**当一个方法在对象上调用时,对象隐式地作为第一个参数传递给方法。也就是说,点运算符左边值为`<expression>`的对象,会自动传给点运算符右边的方法,作为第一个参数。所以,对象绑定到了参数`self`上。
196196

197-
为了自动实现`self`的绑定,Python 区分函数和绑定方法。我们已经在这门课的开始创建了前者,而后者在方法调用时将对象和函数组合到一起。绑定方法的值已经关联了第一个函数,即所调用的实例,当方法调用时实例会被命名为`self`
197+
为了自动实现`self`的绑定,Python 区分函数和绑定方法。我们已经在这门课的开始创建了前者,而后者在方法调用时将对象和函数组合到一起。绑定方法的值已经将第一个函数关联到所调用的实例,当方法调用时实例会被命名为`self`
198198

199199
通过在点运算符的返回值上调用`type`,我们可以在交互式解释器中看到它们的差异。作为类的属性,方法只是个函数,但是作为实例属性,它是绑定方法:
200200

@@ -216,15 +216,15 @@ True
216216
2011
217217
```
218218

219-
函数`getattr`的表现就像运算符那样:它的第一个参数是对象,而名称是定义在类中的方法。之后,`getattr`返回绑定方法的值。另一方面,如果第一个参数是个类,`getattr`会直接返回属性值,它仅仅是个函数。
219+
函数`getattr`的表现就像运算符那样:它的第一个参数是对象,而第二个参数(名称)是定义在类中的方法。之后,`getattr`返回绑定方法的值。另一方面,如果第一个参数是个类,`getattr`会直接返回属性值,它仅仅是个函数。
220220

221221
**实践指南:命名惯例。**类名称通常以首字母大写来编写(也叫作驼峰拼写法,因为名称中间的大写字母像驼峰)。方法名称遵循函数命名的惯例,使用以下划线分隔的小写字母。
222222

223-
有的时候,有些实例变量和方法和对象的维护和一致性相关,我们不想让用户看到或使用它们。它们并不是由类定义的抽象的一部分,而是实现的一部分。Python 的惯例规定,如果属性名称以下划线开始,它只能在方法或类中访问,而不是类的用户
223+
有的时候,有些实例变量和方法的维护和对象的一致性相关,我们不想让用户看到或使用它们。它们并不是由类定义的一部分抽象,而是一部分实现。Python 的惯例规定,如果属性名称以下划线开始,它只能在方法或类中访问,而不能被类的用户访问
224224

225225
## 2.5.4 类属性
226226

227-
有些属性值在指定类的所有对象之间共享。这样的属性关联到类本身,而不是类的任何独立实例。例如,让我们假设银行以固定的利率对余额支付利息。这个利率可能会改变,但是它是在所有账户中共享的单一值。
227+
有些属性值在特定类的所有对象之间共享。这样的属性关联到类本身,而不是类的任何独立实例。例如,让我们假设银行以固定的利率对余额支付利息。这个利率可能会改变,但是它是在所有账户中共享的单一值。
228228

229229
类属性由`class`语句组中的赋值语句创建,位于任何方法定义之外。在更宽泛的开发者社群中,类属性也被叫做类变量或静态变量。下面的类语句以名称`interest``Account`创建了类属性。
230230

@@ -248,7 +248,7 @@ True
248248
0.02
249249
```
250250

251-
但是,单一的对雷属性的赋值语句会改变所有该类实例上的属性值
251+
但是,对类属性的单一赋值语句会改变所有该类实例上的属性值
252252

253253
```py
254254
>>> Account.interest = 0.04
@@ -260,7 +260,7 @@ True
260260

261261
**属性名称。**我们已经在我们的对象系统中引入了足够的复杂性,我们需要规定名称如何解析为特定的属性。毕竟,我们可以轻易拥有同名的类属性和实例属性。
262262

263-
像我们看到的那样,点运算符,由表达式、点和名称组成:
263+
像我们看到的那样,点运算符由表达式、点和名称组成:
264264

265265
```
266266
<expression> . <name>
@@ -273,7 +273,7 @@ True
273273
3. 如果`<name>`不存在于实例属性,那么会在类中查找`<name>`,这会产生类的属性值。
274274
4. 这个值会被返回,如果它是个函数,则会返回绑定方法。
275275

276-
在这个求值过程中,实例属性在类的属性之前查找,就像局部名称具有高于全局的优先级。定义在类中的方法,在求值过程的第三部绑定到了点运算符的对象上。在类中查找名称的过程有额外的差异,在我们引入类继承的时候就会出现。
276+
在这个求值过程中,实例属性在类的属性之前查找,就像局部名称具有高于全局的优先级。定义在类中的方法,在求值过程的第三步绑定到了点运算符的对象上。在类中查找名称的过程有额外的差异,在我们引入类继承的时候就会出现。
277277

278278
**赋值。**所有包含点运算符的赋值语句都会作用于右边的对象。如果对象是个实例,那么赋值就会设置实例属性。如果对象是个类,那么赋值会设置类属性。作为这条规则的结果,对对象属性的赋值不能影响类的属性。下面的例子展示了这个区别。
279279

@@ -327,11 +327,11 @@ True
327327

328328
子类继承了基类的属性,但是可能覆盖特定属性,包括特定的方法。使用继承,我们只需要关注基类和子类之间有什么不同。任何我们在子类未指定的东西会自动假设和基类中相同。
329329

330-
继承也在对象隐喻中有重要作用,不仅仅是一种实用的组织特性。继承意味着在类之间表达“is-a”关系,它和“has-a”关系相反。活期账户是(is-a)一种特殊类型的账户,所以让`CheckingAccount`继承`Account`是继承的合理使用。另一方面,银行拥有(has-a)所管理的银行账户的列表,所以二者都不应继承另一个。反之,账户对象的列表应该自然地表现为银行账户的实例属性。
330+
继承也在对象隐喻中有重要作用,不仅仅是一种实用的组织方式。继承意味着在类之间表达“is-a”关系,它和“has-a”关系相反。活期账户是(is-a)一种特殊类型的账户,所以让`CheckingAccount`继承`Account`是继承的合理使用。另一方面,银行拥有(has-a)所管理的银行账户的列表,所以二者都不应继承另一个。反之,账户对象的列表应该自然地表现为银行账户的实例属性。
331331

332332
## 2.5.6 使用继承
333333

334-
我们通过将放置到类名称后面的圆括号内来指定继承。首先,我们提供`Account`类的特定完整实现,也包含类和方法的文档字符串。
334+
我们通过将基类放置到类名称后面的圆括号内来指定继承。首先,我们提供`Account`类的完整实现,也包含类和方法的文档字符串。
335335

336336
```py
337337
>>> class Account(object):
@@ -363,7 +363,7 @@ True
363363
return Account.withdraw(self, amount + self.withdraw_charge)
364364
```
365365

366-
这里,我们引入了类属性`withdraw_charge`,它特定于`CheckingAccount`类。我们将一个更低的值赋给`interest`属性。我们也定义了新的`withdraw`方法来覆盖定义在`Account`对象中国的行为。类语句组中没有更多的语句,所有其它行为都从基类`Account`中继承。
366+
这里,我们引入了类属性`withdraw_charge`,它特定于`CheckingAccount`类。我们将一个更低的值赋给`interest`属性。我们也定义了新的`withdraw`方法来覆盖定义在`Account`对象中的行为。类语句组中没有更多的语句,所有其它行为都从基类`Account`中继承。
367367

368368
```py
369369
>>> checking = CheckingAccount('Sam')
@@ -375,7 +375,7 @@ True
375375
0.01
376376
```
377377

378-
`checking.deposit`表达式为用于存款的绑定方法,它定义在`Account`类中,当 Python 解析点表达式中的名称时,实例上并没有这个属性,它会在类中查找该名称。实际上,在类中“查找名称”会在原始对象的类的继承链中的每个基类中查找。我们可以递归定义这个过程,为了在类中查找名称:
378+
`checking.deposit`表达式是用于存款的绑定方法,它定义在`Account`类中,当 Python 解析点表达式中的名称时,实例上并没有这个属性,它会在类中查找该名称。实际上,在类中“查找名称”的行为会在原始对象的类的继承链中的每个基类中查找。我们可以递归定义这个过程,为了在类中查找名称:
379379

380380
1. 如果类中有带有这个名称的属性,返回属性值。
381381
2. 否则,如果有基类的话,在基类中查找该名称。
@@ -412,7 +412,7 @@ Python 支持子类从多个基类继承属性的概念,这是一种叫做多
412412
self.balance = 1 # A free dollar!
413413
```
414414

415-
实际上,这个实现就完整了。存款和取款都需要费用,使用定义在`CheckingAccount``SavingsAccount`中的相应函数。
415+
实际上,这个实现就完整了。存款和取款都需要费用,使用了定义在`CheckingAccount``SavingsAccount`中的相应函数。
416416

417417
```py
418418
>>> such_a_deal = AsSeenOnTVAccount("John")
@@ -433,17 +433,17 @@ Python 支持子类从多个基类继承属性的概念,这是一种叫做多
433433
1
434434
```
435435

436-
但是如果引用有歧义呢,比如`withdraw`方法的引用定义在`Account``CheckingAccount`中?下面的图展示了`AsSeenOnTVAccount`类的继承图。每个箭头都从子类指向基类。
436+
但是如果引用有歧义呢,比如`withdraw`方法的引用,它定义在`Account``CheckingAccount`中?下面的图展示了`AsSeenOnTVAccount`类的继承图。每个箭头都从子类指向基类。
437437

438438
![](img/multiple_inheritance.png)
439439

440-
对于像这样的简单“菱形”,Python 从做到右解析名称,之后向上。这个例子中,Python 按下列顺序检查名称,直到找到了具有该名称的属性:
440+
对于像这样的简单“菱形”,Python 从左到右解析名称,之后向上。这个例子中,Python 按下列顺序检查名称,直到找到了具有该名称的属性:
441441

442442
```
443443
AsSeenOnTVAccount, CheckingAccount, SavingsAccount, Account, object
444444
```
445445

446-
对于继承顺序的问题没有正确的解法,因为我们可能会给某个派生类高于其他类的优先级。但是,任何致辞多重继承的编程语言必须始终选择同一个顺序,便于语言的用户预测程序的行为。
446+
继承顺序的问题没有正确的解法,因为我们可能会给某个派生类高于其他类的优先级。但是,任何支持多重继承的编程语言必须始终选择同一个顺序,便于语言的用户预测程序的行为。
447447

448448
**扩展阅读。**Python 使用一种叫做 C3 Method Resolution Ordering 的递归算法来解析名称。任何类的方法解析顺序都使用所有类上的`mro`方法来查询。
449449

@@ -452,7 +452,7 @@ AsSeenOnTVAccount, CheckingAccount, SavingsAccount, Account, object
452452
['AsSeenOnTVAccount', 'CheckingAccount', 'SavingsAccount', 'Account', 'object']
453453
```
454454

455-
这个用于发现方法解析顺序的算法并不是这门课的主题,但是 Python 的原作者使用一篇[原文章的引用](http://python-history.blogspot.com/2010/06/method-resolution-order.html)来描述它。
455+
这个用于查询方法解析顺序的算法并不是这门课的主题,但是 Python 的原作者使用一篇[原文章的引用](http://python-history.blogspot.com/2010/06/method-resolution-order.html)来描述它。
456456

457457
## 2.5.8 对象的作用
458458

@@ -465,4 +465,3 @@ Python 对象系统为使数据抽象和消息传递更加便捷和灵活而设
465465
另一方面,类可能不会提供用于实现特定的抽象的最佳机制。函数式抽象提供了更加自然的隐喻,用于表现输入和输出的关系。一个人不应该强迫自己把程序中的每个细微的逻辑都塞到类里面,尤其是当定义独立函数来操作数据变得十分自然的时候。函数也强制了关注分离。
466466

467467
类似 Python 的多范式语言允许程序员为合适的问题匹配合适的范式。为了简化程序,或使程序模块化,确定何时引入新的类,而不是新的函数,是软件工程中的重要设计技巧,这需要仔细关注。
468-

0 commit comments

Comments
 (0)