1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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
267
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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
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
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
<code>1</code><code>、變量名壓縮</code>
<code> </code><code>class</code>
<code>語句内開頭 有兩個下劃線,但結尾沒有兩個下劃線的變量名會自動擴張,進而包含所在類的名稱。例如:象spam類内__x這樣的變量名會自動變成 _spam__x.原始的變量名會在開頭家一個下劃線,然後是再加上所在類的類名。這一規則适用了每個開頭有兩個下劃線 的變量名,包括方法名稱和執行個體屬性名稱。(例如:在spam類内,</code><code>self</code><code>.__x執行個體屬性會變成</code><code>self</code><code>._spam__x)</code>
<code>2</code><code>、方法是對象:綁定或無綁定</code>
<code> </code><code>無綁定類方法對象: 無</code><code>self</code>
<code> </code><code>通過對類進行點号運算進而擷取函數的屬性,會傳回無綁定方法對象,調用該方法時,必須提供執行個體對象作為第一個參數,在python3.</code><code>0</code><code>中,一個無綁定方法和一個簡單函數相同。可以通過類名來調用,在python2.</code><code>6</code><code>中,他是一個特殊的類型,并且不提供一個執行個體就無法調用</code>
<code> </code><code>綁定執行個體方法對象: </code><code>self</code><code>+</code><code>函數對</code>
<code> </code><code>通過對執行個體進行全運算,進而擷取類的汗水屬性,會傳回綁定方法對象。python在綁定方法對象中自動實作執行個體和函數的打包,是以不用傳遞執行個體去調用該方法。</code>
<code> </code><code>例如:</code>
<code>spam:</code>
<code> </code><code>def</code>
<code>doit(</code><code>self</code><code>,message):</code>
<code> </code><code>print</code><code>(message)</code>
<code> </code>
<code> </code><code>在下面代碼中,會傳回綁定方法對象,把執行個體(object1)和方法函數(spam.doit)打包起來。我們可以把這個綁定方法指派給另外一個變量。然後像函數那樣進行調用。</code>
<code> </code><code>object1</code><code>=</code>
<code>spam()</code>
<code> </code><code>x</code><code>=</code>
<code>object1.doit</code>
<code> </code><code>x(</code><code>‘hello world‘</code><code>)</code>
<code> </code><code>另一方面,如果對類進行點号運算來獲得doit就會獲得無綁定方法對象。也就是函數對象的引用值。要調用這個類方法時,必須傳入執行個體作為最左側參數</code>
<code> </code><code>object2</code><code>=</code>
<code> </code><code>t</code><code>=</code>
<code>spam.doit</code>
<code> </code><code>t(object2,</code><code>‘howdy‘</code><code>)</code>
<code> </code><code>擴充一下:如果我們引用的</code><code>self</code><code>屬性是引用類中的函數,那麼相同的規則也适用于類的方法。</code><code>self</code><code>.method表達式是邦定方法,因為</code><code>self</code><code>是執行個體對象。</code>
<code>c:</code>
<code> </code><code>def</code>
<code>m1(</code><code>self</code><code>,n):</code>
<code> </code><code>print</code><code>(</code><code>‘m1=‘</code><code>,n)</code>
<code>m2(</code><code>self</code><code>,t):</code>
<code> </code><code>x</code><code>=</code>
<code>self</code><code>.m1 </code><code>#這裡是通過執行個體和方法打包,是綁定方法。</code>
<code> </code><code>x(t)</code><code>#在這裡調用綁定方法不需要傳入執行個體</code>
<code> </code><code>print</code><code>(</code><code>‘m2=‘</code><code>,t)</code>
<code> </code><code>c</code><code>=</code>
<code>c()</code>
<code> </code><code>c.m2(</code><code>88</code><code>)</code>
<code> </code><code>print</code><code>(</code><code>‘#‘</code><code>*</code><code>8</code><code>)</code>
<code> </code><code>c.m2(c,</code><code>77</code><code>)</code>
<code> </code><code>print</code><code>(</code><code>‘-‘</code><code>*</code><code>8</code><code>)</code>
<code>b:</code>
<code> </code><code>print</code><code>(</code><code>‘m1=‘</code><code>,n)</code>
<code> </code><code>x</code><code>=</code>
<code>b.m1 </code><code>#這裡通過類來擷取類中的函數,是無綁定方法對象</code>
<code> </code><code>x(</code><code>self</code><code>,t)</code><code>#這裡使用時需要傳入一個類對象。</code>
<code> </code><code>print</code><code>(</code><code>‘m2=‘</code><code>,t)</code>
<code> </code><code>b</code><code>=</code>
<code>b()</code>
<code> </code><code>b.m2(b,</code><code>99</code><code>)</code>
<code> </code><code>print</code><code>(</code><code>‘@‘</code><code>*</code><code>8</code><code>)</code>
<code> </code><code>b.m2(</code><code>66</code><code>)</code>
<code> </code><code>#輸出結果:</code>
<code> </code><code>m1</code><code>=</code>
<code>88</code>
<code> </code><code>m2</code><code>=</code>
<code> </code><code>########</code>
<code>77</code>
<code> </code><code>-</code><code>-</code><code>-</code><code>-</code><code>-</code><code>-</code><code>-</code><code>-</code>
<code>99</code>
<code> </code><code>@@@@@@@@</code>
<code>66</code>
<code>3</code><code>、在python3.</code><code>0</code><code>中無綁定方法是函數</code>
<code> </code><code>在python3.</code><code>0</code><code>中已經删除</code><code>"無綁定方法"</code><code>的概念,但是還是可以使用。在上面介紹的綁定方法,在python3.</code><code>0</code><code>中隻當作一個簡單函數來使用。簡單函數不期待傳遞給他一個執行個體,非簡單函數期待傳遞一個執行個體。</code>
<code> </code><code>此外:在python3.</code><code>0</code><code>中不使用一個執行個體而調用一個方法沒有問題,隻要這個方法不期待一個執行個體,并且你通過類調用它而不是通過一個執行個體調用它。也就是說,隻有對通過執行個體調用,python3.</code><code>0</code><code>才會向方法傳遞一個執行個體。當通過一個類調用的時候,隻有在方法期待一個執行個體的時候,才必須手動傳遞一個執行個體。</code>
<code>selfless:</code>
<code>__init__(</code><code>self</code><code>,data):</code>
<code> </code><code>self</code><code>.data</code><code>=</code>
<code>data</code>
<code>selfless(arg1,arg2):</code>
<code> </code><code>return</code>
<code>arg1</code><code>+</code><code>arg2</code>
<code>normal(</code><code>self</code><code>,arg1,arg2):</code>
<code>self</code><code>.data</code><code>+</code><code>arg1</code><code>+</code><code>arg2</code>
<code>selfless(</code><code>2</code><code>)</code>
<code> </code><code>print</code><code>(x.normal(</code><code>3</code><code>,</code><code>4</code><code>))</code>
<code> </code><code>print</code><code>(selfless.normal(x,</code><code>3</code><code>,</code><code>4</code><code>))</code>
<code> </code><code>print</code><code>(selfless.selfless(</code><code>3</code><code>,</code><code>4</code><code>)) </code><code>#在python3.0中可以通過一個類去調用這個類的普通方法,但是在python2.6中不行,會抱錯。</code>
<code> </code><code>#print(x.selfess(3,4)) 不能通過執行個體去調用一個類的普通方法</code>
<code>4</code><code>、多重內建</code>
<code> </code><code>在傳統類中(預設的類,直到python3.</code><code>0</code><code>),屬性搜尋處理對所有路徑深度優先 ,直到繼承樹的頂端,然後從左到右</code>
<code> </code><code>在新式類(以及python.</code><code>30</code><code>的所有類中)屬性搜尋處理沿着樹層級,以及更寬廣優先的方式。</code>
<code> </code><code>例如:使用__dict__列出執行個體屬性</code>
<code> </code><code>class</code>
<code>listinstance:</code>
<code> </code><code>‘‘‘</code>
<code> </code><code>mix-in class that provides a formatted print() or str() of instance of via inheritance of __str__, coded here:displays instance attrs only;self is the instance of lowest class;</code>
<code> </code><code>uses __x names to avoid clashing with client‘s attrs</code>
<code>__str__(</code><code>self</code><code>):</code>
<code>‘<instance of %s, adderss %s:\n%s>‘</code><code>%</code><code>(</code>
<code> </code><code>self</code><code>.__class__.__name__,</code><code>#每個執行個體都有一個内置的__class__屬性,它引用建立 自己的類,并且每一個類都有一個__name__屬性。他引用頭部的名稱。</code>
<code> </code><code>id</code><code>(</code><code>self</code><code>), </code><code>#傳回該對象的記憶體位址</code>
<code> </code><code>self</code><code>.__attrnames()</code>
<code> </code><code>)</code>
<code>__attrnames(</code><code>self</code><code>):</code>
<code> </code><code>result</code><code>=</code>
<code>‘‘</code>
<code> </code><code>for</code>
<code>attr</code><code>in</code>
<code>sorted</code><code>(</code><code>self</code><code>.__dict__):</code>
<code> </code><code>result</code><code>+</code><code>=</code><code>‘\tname %s=%s\n‘</code><code>%</code><code>(attr,</code><code>self</code><code>.__dict__[attr])</code>
<code>result</code>
<code> </code><code>s</code><code>=</code>
<code>spam(</code><code>12</code><code>)</code>
<code> </code><code>print</code><code>(s)</code>
<code> </code><code>#輸出:</code>
<code> </code><code><instance of spam, adderss</code><code>3073187084</code><code>:</code>
<code> </code><code>name data</code><code>=</code><code>12</code>
<code> </code><code>></code>
<code> </code><code>例如:使用</code><code>dir</code><code>列出繼承的所有屬性</code>
<code> </code><code>class</code>
<code>listinherited:</code>
<code> </code><code>‘‘‘</code>
<code> </code><code>use dir() to collect both instance attrs and names</code>
<code> </code><code>inherited from its classes; python3.0 shows more</code>
<code> </code><code>names than 2.6 because of the implied object supperclass</code>
<code> </code><code>in the new-style class model; getattr() fetches inherited</code>
<code> </code><code>names not in self.__dict__;use __str__,not __repr__</code>
<code> </code><code>or else this loops when printing bound methods</code>
<code> </code><code>def</code>
<code> </code><code>return</code>
<code>‘<instance of %s, address %s:\n%s>‘</code><code>(</code><code>self</code><code>.__class_.__name,</code>
<code> </code><code>id</code><code>(</code><code>self</code><code>),</code>
<code> </code><code>self</code><code>.__attrnames())</code>
<code> </code><code>result</code><code>=</code>
<code> </code><code>for</code>
<code>dir</code><code>(</code><code>self</code><code>):</code>
<code> </code><code>if</code>
<code>attr[:</code><code>2</code><code>]</code><code>=</code><code>=</code>
<code>‘__‘</code> <code>and</code> <code>attr[</code><code>-</code><code>2</code><code>:]</code><code>=</code><code>=</code>
<code>‘__‘</code><code>:</code>
<code> </code><code>result</code><code>+</code><code>=</code><code>‘\tname %s = <>‘</code><code>%</code><code>attr</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>result</code><code>+</code><code>=</code>
<code>‘\tname %s=%s\n‘</code><code>%</code><code>(attr,</code><code>getattr</code><code>(</code><code>self</code><code>,attr))</code>
<code> </code><code>例如:列出類樹中的每個對象的屬性</code>
<code>listtree:</code>
<code> </code><code>mix-in that returns an __str__ trace of the entire class</code>
<code> </code><code>tree and all its objects‘attrs at and above self;</code>
<code> </code><code>run by print(),str() returns constructed string;</code>
<code> </code><code>uses __x attr names to void impacting clients;</code>
<code> </code><code>uses generator expr to recurse to superclasses;</code>
<code> </code><code>uses str.format() to make substituion clear</code>
<code> </code><code>self</code><code>.__visited</code><code>=</code>
<code>{}</code>
<code>‘<instance of {0}, address {1}:\n{2}{3}‘</code><code>.</code><code>format</code><code>(</code>
<code> </code><code>self</code><code>.__class__.__name__,</code>
<code> </code><code>id</code><code>(</code><code>self</code><code>),</code>
<code> </code><code>self</code><code>.__attrnames(</code><code>self</code><code>,</code><code>0</code><code>),</code>
<code> </code><code>self</code><code>.__listclass(</code><code>self</code><code>.__class_,</code><code>4</code><code>)</code>
<code>__listclass(</code><code>self</code><code>,aclass,indent):</code>
<code> </code><code>dots</code><code>=</code>
<code>‘.‘</code><code>*</code><code>indent</code>
<code> </code><code>if</code>
<code>aclass</code><code>in</code>
<code>self</code><code>.__visited:</code>
<code>‘\n{0}<class {1}:,address {2}:(see above)>\n‘</code><code>.</code><code>format</code><code>(</code>
<code> </code><code>dots,</code>
<code> </code><code>aclass.__name,</code>
<code> </code><code>id</code><code>(aclass)</code>
<code> </code><code>)</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>self</code><code>.__visited[aclass]</code><code>=</code><code>true</code>
<code> </code><code>genabove</code><code>=</code>
<code>(</code><code>self</code><code>.__listclass(c,indent</code><code>+</code><code>4</code><code>)</code><code>for</code>
<code>c</code><code>in</code>
<code>aclass.__base__)</code>
<code>‘\n{0}<class {1} , address {2}:\n{3}{4}{5}>\n‘</code><code>.</code><code>format</code><code>(</code>
<code> </code><code>aclass.__name__,</code>
<code> </code><code>id</code><code>(aclass),</code>
<code> </code><code>self</code><code>.__attrnames(aclass,indent),</code>
<code> </code><code>‘‘.join(genabove),</code>
<code> </code><code>dots</code>
<code>__attrnames(</code><code>self</code><code>,obj,indent):</code>
<code> </code><code>spaces</code><code>=</code>
<code>‘ ‘</code> <code>*</code> <code>(indent</code><code>+</code><code>4</code><code>)</code>
<code>sorted</code><code>(obj.__dict__):</code>
<code> </code><code>if</code>
<code>attr.startwith(</code><code>‘__‘</code><code>)</code><code>and</code>
<code>attr.endwith(</code><code>‘__‘</code><code>):</code>
<code> </code><code>resutl</code><code>+</code><code>=</code><code>spaces</code><code>+</code><code>‘{0}=<>\n‘</code><code>.</code><code>format</code><code>(attr)</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>result</code><code>+</code><code>+</code><code>space</code><code>+</code><code>‘{0}={1}\n‘</code><code>.</code><code>format</code><code>(attr,</code><code>getattr</code><code>(obj,attr))</code>
<code>4</code><code>、新式類</code>
<code> </code><code>對于python3.</code><code>0</code><code>來說,所有類都是我們所謂的”新式類“,不管他們是否顯示繼承</code><code>object</code><code>.所有類都繼承自</code><code>object</code><code>.不管顯式還是隐式,所有對象都是</code><code>object</code><code>的執行個體</code>
<code> </code><code>在python2.</code><code>6</code><code>及其以前版本,類必須繼承自類看作是新式”</code><code>object</code><code>,并且獲得新式類的特性。</code>
<code>5</code><code>、新式類的變化</code>
<code> </code><code>1</code><code>)類和類型合并</code>
<code> </code><code>類現在就是類型,并且類型現在就是類,實際上,這二者基本上是同義詞。</code><code>type</code><code>(i)内置函數傳回一個建立這個執行個體i的類。而不是一個通用執行個體類型,并且,通常是和i.__class__相同。此外,雷氏</code><code>type</code><code>類的執行個體,</code><code>type</code><code>可能子類化</code>
<code>6</code><code>、__slots__</code>
<code> </code><code>如果一個字類繼承一個沒有__slots__的超類,那麼超類的__dict__屬性總是可以通路的,使得字類的__slots__沒有意義</code>
<code> </code><code>如果一個超類定義了一個與超類相同的slots名稱,超類slots定義的名稱隻有通過從直接超類擷取其描述符才能通路</code>
<code> </code><code>由于一個超類__slots__聲明的含義受到它出現其中類的限制,是以一個字類将有一個__dict__除非他也聲明了一個__slots__</code>
<code> </code><code>通常從列出執行個體屬性這方面來看,多數類的slots可能需要手動類樹爬升、</code><code>dir</code><code>用法或者把slot名稱當作不同的名稱領域的政策</code>
<code>7</code><code>、特性</code>
<code> </code><code>适用條件是這個類必須繼承</code><code>object</code>
<code>classic:</code>
<code>getx(</code><code>self</code><code>)</code>
<code>self</code><code>.__x</code>
<code>setx(</code><code>self</code><code>,data):</code>
<code> </code><code>self</code><code>.__x</code><code>=</code><code>data</code>
<code>delx(</code><code>self</code><code>)</code>
<code> </code><code>self</code><code>.__x</code><code>=</code>
<code>none</code>
<code>property</code><code>(getx,setx,delx,</code><code>none</code><code>)</code>
<code>8</code><code>、__getattribute__方法隻适用于新式類,可以讓類攔截所有屬性的引用,而不是局限于未定義的引用</code>
<code>9</code><code>、靜态方法和類方法</code>
<code> </code><code>不用一個執行個體就可以調用 :靜态方法</code>
<code> </code><code>傳遞一個類而不是一個執行個體:類方法</code>
<code>10</code><code>、靜态方法和類方法使用執行個體</code>
<code> </code><code>靜态方法: </code>
<code> </code><code>numinstances</code><code>=</code>
<code>0</code>
<code>__init__(</code><code>self</code><code>):</code>
<code> </code><code>spam.numinstances</code><code>+</code><code>=</code><code>1</code>
<code>printnuminstance():</code>
<code> </code><code>print</code><code>(</code><code>"number of instance:"</code><code>,spam.numinstances)</code>
<code> </code><code>printnuminstance</code><code>=</code>
<code>staticmethod</code><code>(printnuminstance)</code>
<code> </code><code>a</code><code>=</code>
<code> </code><code>spam.printnuminstance()</code>
<code> </code><code>a.printnuminstance()</code>
<code> </code><code>繼承:</code>
<code>sub(spam):</code>
<code> </code><code>print</code><code>(</code><code>‘extra stauff...‘</code><code>)</code>
<code> </code><code>spam.printnuminstance()</code>
<code>sub()</code>
<code> </code><code>sub.printnuminstance()</code>
<code> </code><code>類方法</code>
<code>printnuminstance(</code><code>cls</code><code>):</code>
<code> </code><code>print</code><code>(</code><code>"num of instnace:"</code><code>,</code><code>cls</code><code>.numinstances)</code>
<code>classmethod</code><code>(printnuminstance)</code>
<code> </code><code>a,b</code><code>=</code>
<code>spam(),spam()</code>
<code> </code><code>繼承方法同靜态方法相同</code>
<code>11</code><code>、裝飾器和元類</code>
<code> </code><code>@staticmethod</code>