Skip to content

Commit c113806

Browse files
committed
qrcode for qqGroup
1 parent 686cbbd commit c113806

File tree

2 files changed

+4
-256
lines changed

2 files changed

+4
-256
lines changed

README.md

Lines changed: 4 additions & 256 deletions
Original file line numberDiff line numberDiff line change
@@ -1,261 +1,9 @@
11
# fluent-python
2-
《流畅的Python》
3-
### 英文原版:
4-
http://shop.oreilly.com/product/0636920032519.do
5-
6-
### 原书名:
7-
《Fluent Python 副标题 Clear, Concise, and Effective Programming》
8-
9-
### 特色:
10-
>Learn how to write idiomatic, effective Python code by leveraging its best features. Python's simplicity quickly lets you become productive with it, but this often means you aren’t using everything the language has to offer. By taking you through Python’s key language features and libraries, this practical book shows you how to make your code shorter, faster, and more readable all at the same time—what experts consider Pythonic.
11-
12-
>Many programmers who learn Python basics fall into the trap of reinventing the wheel because of past experience in other languages, and try to bend the language to patterns that don't really apply to it. Author Luciano Ramalho, a Python Software Foundation member and Python programmer for 15 years, helps you drop your accent from another language so you can code Python fluently.
13-
14-
>Learn practical applications of generators for database processing
15-
Rethink some design patterns in a Python context
16-
Examine attribute descriptors and when to use them: the key to ORMs
17-
Explore Pythonic objects: protocols versus interfaces, abstract base classes and multiple inheritance
18-
19-
### 作者:
20-
Luciano Ramalho
21-
22-
### 出版社:
23-
O'Reilly Media
24-
25-
## 纸书出版日期:
26-
August 2015 (美国东部时间.)
27-
28-
## 全书页数:
29-
750
30-
31-
*************
32-
33-
34-
`预览`
35-
第十二章 继承该如何是好
36-
**********************************************
37-
38-
>[我们]开始去推动继承思想,使其成为了新手也可以构建以前只有原专家才可以设计的框架。
39-
40-
>— 阿兰.凯《Smalltalk的早期历史》
41-
42-
本章涉及到了继承和子类化,这里有两处特别强调的针对Python的细节:
43-
44-
- 子类化内建类型的陷阱
45-
- 多重继承与方法解析顺序
46-
47-
很多人认为多重继承带来的麻烦远大于其带来的好处。
48-
49-
然而,由于Java特别出色并具有广泛的影响力,这就意味着,在实际编程活动中很多程序员并没有见过多重继承。这就是为什么我们通过两个重要的项目来阐明多重继承的适应范围:`Tkinter GUI`套件,以及Django web 框架的原因。
50-
51-
我们从子类化内建类型的问题开始。余下的章节会用案例研究并学习多重继承,讨论在构建类的分层设计时会遇到的问题。
52-
53-
## 子类化内建类型是需要些技巧的
54-
在Python2.2之前,子类化`list`或者`dict`这样的内建类型是不可能的。打那以后,Python虽然可以做到子类化内建类型,但是仍然要面对的重要警告是:内建的代码(由C语言重写)并不会调用被通过用户自定义类所覆盖的特殊方法。
55-
56-
对问题的准确描述都放在了`PyPy`文档,以及内建类型的子类化一节中的`PyPy和CPython之间差异`
57-
58-
>正式地来说,Cpython对完全地重写内建类型的子类方法时是否明确地调用毫无规则可循。大略上,这些方法从来没有被其他的相同对象的内建方法所调用。例如,`dict`子类中的重写`__getitem__()`不会被`get()`这样的内建方法调用。
59-
60-
例子12-1阐明了此问题。
61-
62-
*例子12-1。重写的`__setitem__``dict``__init__``__update__`方法所忽略。*
63-
64-
************************
65-
66-
```python
67-
>>> class DoppelDict(dict):
68-
... def __setitem__(self, key, value):
69-
... super(DoppelDict, self).__setitem__(key, [value] * 2) # 1...
70-
>>> dd = DoppelDict(one=1) # 2
71-
>>> dd
72-
{'one': 1}
73-
>>> dd['two'] = 2 # 3
74-
>>> dd
75-
{'one': 1, 'two': [2, 2]}
76-
>>> dd.update(three=3) # 4>
77-
>> dd
78-
{'three': 3, 'one': 1, 'two': [2, 2]}
79-
```
80-
81-
1:存储时`DoppelDict.__setitem__`会使值重复(由于这个不好原因,因此必须有可见的效果)。它在委托到超类时才会正常运行。
82-
83-
2:继承自`dict``__init__`方法,明确地忽略了重写的`__setitem__``'one'`的值并没有重复。
84-
85-
3:`[]`运算符调用`__setitem__`,并如所希望的那样运行:`'two'`映射到了重复的值`[2, 2]`
86-
87-
4:`dict``update`方法也没有使用我们定义的`__setitem__`:值`'three'`没有被重复。
88-
89-
该内建行为违反了面向对象的基本准则:方法的搜索应该总是从目标实例(`self`)的类开始,甚至是调用发生在以超类实现的方法之内部。在这样的悲观的情形下,
90-
91-
问题是在一个实例内部没有调用的限制,例如,不论`self.get()`是否调用`self.__getitem__()`,都会出现会被内建方法所调用其他类的方法被重写。下面是改编自`PyPy文档`的例子:
92-
93-
例子12-2。`AnswerDict``__getitem__``dict.update`所忽略。
94-
95-
```python
96-
>>> class AnswerDict(dict):
97-
... def __getitem__(self, key): # 1...
98-
return 42
99-
...
100-
>>> ad = AnswerDict(a='foo') # 2
101-
>>> ad['a'] # 3
102-
42
103-
>>> d = {}
104-
>>> d.update(ad) # 4
105-
>>> d['a'] # 5
106-
'foo'
107-
>>> d
108-
{'a': 'foo'}
109-
```
110-
111-
1:`AnserDict.__getitem__`总是返回`42`,不论键是什么。
112-
113-
2:`ad`是一个带有键值对`('a', 'foo')``AnswerDict`
114-
115-
3:`ad['a']`如所期望的那样返回42。
116-
117-
4:`d`是一个普通使用`ad`更新的`dict`实例。
1182

119-
5:`dict.update`方法忽略了`AnserDict.__getitem__`
120-
121-
>##### 警告
122-
直接地子类化类似`dict`或者`list`或者`str`这样的内建类型非常容易出错,因为大多数的内建方法会忽略用户所定义的重写方法。从被设计成易于扩展的`collections`模块的`UserDict``UserList``UserString`派生类,而不是子类化内建。
123-
124-
如果你子类化`collections.UserDict`而不是`dict`,那么例子12-1和例子12-2中的问题都会被该解决。见例子12-3。
125-
126-
*例子12-3。`DoppelDict2``AnswerDict2`一如所希望的运行,因为它们扩展的是UserDict而不是dict。*
127-
***************
128-
129-
```python
130-
>>> import collections
131-
>>>
132-
>>> class DoppelDict2(collections.UserDict):
133-
... def __setitem__(self, key, value):
134-
... super().__setitem__(key, [value] * 2)
135-
...
136-
>>> dd = DoppelDict2(one=1)
137-
>>> dd
138-
{'one': [1, 1]}
139-
>>> dd['two'] = 2
140-
>>> dd
141-
{'two': [2, 2], 'one': [1, 1]}
142-
>>> dd.update(three=3)
143-
>>> dd
144-
{'two': [2, 2], 'three': [3, 3], 'one': [1, 1]}
145-
>>>
146-
>>> class AnswerDict2(collections.UserDict):
147-
... def __getitem__(self, key):
148-
... return 42
149-
...
150-
>>> ad = AnswerDict2(a='foo')
151-
>>> ad['a']
152-
42
153-
>>> d = {}
154-
>>> d.update(ad)
155-
>>> d['a']
156-
42
157-
>>> d
158-
{'a': 42}
159-
```
160-
161-
为了估量内建的子类工作所要求体验,我重写了例子3-8中`StrKeyDict`类。继承自`collections.UserDict`的原始版本,由三种方法实现:`__missing__``___contains__``__setitem__`
162-
163-
总结:本节所描述的问题仅应用于在C语言内的方法委托实现内建类型,而且仅对用户定义的派生自这些的类型的类有效果。如果你在Python中子类化类编程,比如,`UserDict`或者`MutableMapping`,你不会遇到麻烦的。
164-
165-
还有问题就是,有关继承,特别地的多重继承:Python如何确定哪一个属性应该使用,如果超类来自并行分支定义相同的名称的属性,答案在下面一节。
166-
167-
### 多重继承以及方法解析顺序
168-
当不关联的祖先类实现相同名称的方法时,任何语言实现多重继承都需要解决潜在的命名冲突。这称做“钻石问题”,一如图表12-1和例子12-4所描述。
169-
170-
图片:
171-
![fluent python_c12_4](https://cloud.githubusercontent.com/assets/10941075/9581132/1b129350-5030-11e5-9229-0387d4bfb991.png)
172-
173-
174-
图表12-1.左边:UML类图表阐明了“钻石问题”。右边:虚线箭头为例子12-4描绘了Python MRO(方法解析顺序).
175-
例子12-4. diamond.py:类A,B, C,和D构成了图表12-1中的图。
176-
177-
```python
178-
class A:
179-
def ping(self):
180-
print('ping:', self)
181-
182-
183-
class B(A):
184-
def pong(self):
185-
print('pong:', self)
186-
187-
188-
class C(A):
189-
def pong(self):
190-
print('PONG:', self)
191-
192-
193-
class D(B, C):
194-
195-
def ping(self):
196-
super().ping()
197-
print('post-ping:', self)
198-
199-
def pingpong(self):
200-
self.ping()
201-
super().ping()
202-
self.pong()
203-
super().pong()
204-
C.pong(self)
205-
206-
```
207-
208-
注意类`B``C`都实现了`pong`方法。唯一的不同是`C.pong`输出大写的单词`PONG`
209-
210-
如果你对实例`D`调用`d.pong()`,实际上哪一个`pong`方法会运行呢?对于C++程序员来说他们必须具有使用类名称调用方法,以解决这个模棱两可的问题。这样的问题在Python中也能够解决。看下例子12-5就知道了。
211-
212-
例子12-5.对类D的实例的pong方法调用的两种形式。
213-
214-
```python
215-
>>> from diamond import *
216-
>>> d = D()
217-
>>> d.pong() # 1
218-
pong: <diamond.D object at 0x10066c278>
219-
>>> C.pong(d) # 2
220-
PONG: <diamond.D object at 0x10066c278>
221-
```
222-
1: 简单地调用`d.pong`导致B的运行。
223-
2: 你可以总是直接地对调用超类的方法,传递实例作为明确的参数。
224-
225-
`d.pong()`这样的模棱两可的调用得以解决,因为Python在穿越继承图时,遵循一个特定的顺序。这个顺序就叫做MRO:方法解析顺序。类有一个被称为`__mro__`的属性,它拥有使用MRO顺序的超类的引用元组,即,当前的类的所有到`object`类的路径。拿类`D`来说明什么是`__mro__`(参见 图表12-1):
226-
227-
```python
228-
>>> D.__mro__
229-
(<class 'diamond.D'>, <class 'diamond.B'>, <class 'diamond.C'>,
230-
<class 'diamond.A'>, <class 'object'>)
231-
```
232-
233-
推荐的调用超类的委托方法就是内建的`super()`函数,这样做是因为在Python3中较易使用,就像例子12-4中的类D的`pingpong`方法所阐述的那样。不过,有时候忽略MRO,对超类直接地调用方法也是也可以的,而且很方便。例如,`D.ping`方法可以这样写:
234-
235-
```python
236-
def ping(self):
237-
A.ping(self) # instead of super().ping()
238-
print('post-ping:', self)
239-
```
240-
241-
注意,当调用直接调用一个类的实例时,你必须明确地传递`self`,因为你访问的是`unbound method`
242-
243-
不过,这是最安全的而且更未来化的使用`super()`,特别是在调用一个框架的方法时,或者任何不受你控制的类继承时。例子12-6演示了在调用方法时`super()`对MRO的遵循。
244-
245-
例子12-6。使用`super()`去调用`ping`(源码见例子12-4)。
246-
247-
```python
248-
```
249-
250-
251-
## 真实世界中的多重继承
252-
## 应对多重继承
253-
#### 1. 接口继承和接口实现之间的区别
3+
《流畅的Python》
2544

255-
##### 继承
5+
## 交流QQ群 211766903
2566

257-
#### 2. 使用ABC让接口更清晰
258-
#### 3. 为了代码重复利用而使用mixin
7+
扫码进群:
2598

260-
## 一个当代的例子:Django通用视图中的mixin
261-
>##### 注释
9+
![qq_cqrcode](./images/the_qrcode_for_qq_group.png)

images/the_qrcode_for_qq_group.png

7.18 KB
Loading

0 commit comments

Comments
 (0)