練習 41. 學著去說面向?qū)ο?/h1>
在這個練習中骤星,我要教你如何去說“面向?qū)ο蟆薄N宜龅木褪墙o你一些你需要了解的詞和定義。然后我會給出一些需要填空的句子讓你去理解败明。最后,你要完成一個大練習太防,從而在大腦中鞏固這些句子妻顶。
詞匯訓練
(注:為了方便理解,定義保留英文原文。)
類(class) :告訴 Python 創(chuàng)建一個新類型的東西(Tell Python to make a new type of thing)讳嘱。
對象(object)兩種含義:最基本類型的東西, 任何實例幔嗦。(the most basic type of thing, and any instance of something.)
實例(instance) :當你告訴 Python 創(chuàng)建一個類的時候你所得到的東西。(What you get when you tell Python to create a class.)
def :你如何在類里面定義一個函數(shù)沥潭。(How you define a function inside a class.)
self :在一個類的函數(shù)里面邀泉,self 是被訪問的實例/對象的一個變量。(Inside the functions in a class, self is a variable for the instance/object
being accessed.)
繼承(inheritance) :關(guān)于一個類能從另一個類那里繼承它的特征的概念钝鸽,很像你和你的父母汇恤。(The concept that one class can inherit traits from another class, much like you and your parents.)
組合(composition) :關(guān)于一個類可以由其他一些類構(gòu)成的概念, 很像一輛車包含幾個輪子。(The concept that a class can be composed of other classes as parts, much like how a car has wheels.)
屬性(attribute) :類所擁有的從組合那里得到的特性拔恰,通常是變量屁置。(A property classes have that are from composition and are usually variables.)
is-a :一種用來表達某物繼承自一種東西的表述, 就像“三文魚是一種魚”。(A phrase to say that something inherits from another, as in a “salmon” is a “fish.”)
has-a :一種用來表達某物是由一些東西組成或具有某種特性的表述仁连,就像“三文魚有一個嘴巴”蓝角。(A phrase to say that something is composed of other things or has a trait, as in “a salmon has-a mouth.”)
花點時間為這些術(shù)語做一些閃詞卡(flash cards)并記住它們,雖然在你完成這個練習之前單純的記憶沒有任何意義饭冬,但你必須要先了解這些基礎(chǔ)的詞匯使鹅。
短語訓練
接下來是一些 Python 代碼片段以及右邊的解釋。
class X(Y)
:
創(chuàng)建一個名為 X 并繼承自 Y 的類昌抠。
(“Make a class named X that is-a Y.”)
class X(object): def __init__(self, J)
類 X 有一個帶有 self 和 J 參數(shù)的 __init__
函數(shù)患朱。
(“class X has-a __init__
that takes self and J parameters.”)
class X(object): def M(self, J)
:
類 X 有一個帶有 self 和 J 參數(shù)的 M 函數(shù)。
(“class X has-a function named M that takes self and J parameters.”)
foo = X()
:
設(shè) foo 為類 X 的一個實例炊苫。
(“Set foo to an instance of class X.”)
foo.M(J)
從 foo 那里獲取 M 函數(shù)裁厅,并用 self 和 J 參數(shù)來調(diào)用它。
(“From foo, get the M function, and call it with parameters self, J.”)
foo.K = Q
從 foo 那里獲取 K 屬性侨艾,并設(shè)它為 Q执虹。
(“From foo, get the K attribute, and set it to Q.”)
在上述每一句中,當你看到 X, Y, M, J, K, Q, 以及 foo, 你可以把它們當做空格唠梨,比如袋励,我還可以把這些句子寫成:
“Make a class named ??? that is-a Y.”
(創(chuàng)建一個名為 ??? 的類,它繼承自 Y当叭。)“class ??? has-a
__init__
that takes self and ??? parameters.”
(類 ??? 有一個帶了 self 和 ??? 參數(shù)的__init__
茬故。)“class ??? has-a function named ??? that takes self and ??? parameters.”
(類 ??? 有一個名為 ??? 的函數(shù),這個函數(shù)帶有 self 和 ??? 兩個參數(shù)蚁鳖。)“Set foo to an instance of class ???.”
(設(shè) foo 為類 ??? 的一個實例磺芭。)“From foo, get the ??? function, and call it with self=??? and parameters ???.”
(從 foo 那里獲取 ??? 函數(shù),并用self=???
以及參數(shù) ??? 來調(diào)用它醉箕。)“From foo, get the ??? attribute, and set it to ???.”
(從 foo 那里獲取 ??? 屬性钾腺,把它設(shè)為 ???甘邀。)
同樣地,把這些短語寫到一些閃詞卡上垮庐,然后記一記松邪。把 Python 代碼片段放在正面,解釋的句子放在背面哨查,你必須每次都正確說出每一個短語的意思逗抑。不是說得類似就行,而是要一模一樣寒亥。
綜合訓練
最后一項準備工作是把詞匯訓練和短語訓練結(jié)合在一起邮府,以下是訓練內(nèi)容:
做一個短語卡然后練習記憶。
把它翻過來溉奕,讀句子褂傀,如果在句子中看到詞匯訓練中的詞匯,就找到相應(yīng)的詞匯卡片加勤。
練習記憶這些詞匯卡片仙辟。
堅持練習,要是你感到有些累鳄梅,就休息一下再繼續(xù)叠国。
一個閱讀測試
現(xiàn)在我有一個小的 Python 腳本來幫助你掌握這些詞匯和短語,并且能夠無限運行戴尸。這段腳本很簡單粟焊,你應(yīng)該能夠看明白,它所做的事情就是用一個叫做 urllib 的圖書館來下載一列單詞孙蒙。以下是腳本代碼项棠,你需要輸入到 oop_test.py 這個文件里來使用:
ex41.py
1 import random
2 from urllib.request import urlopen
3 import sys
4
5 WORD_URL = "http://learncodethehardway.org/words.txt"
6 WORDS = []
7
8 PHRASES = {
9 "class %%%(%%%):":
10 "Make a class named %%% that is-a %%%.",
11 "class %%%(object):\n\tdef __init__(self, ***)" :
12 "class %%% has-a __init__ that takes self and *** params.",
13 "class %%%(object):\n\tdef ***(self, @@@)":
14 "class %%% has-a function *** that takes self and @@@ params.",
15 "*** = %%%()":
16 "Set *** to an instance of class %%%.",
17 "***.***(@@@)":
18 "From *** get the *** function, call it with params self @@@.",
19 "***.*** = '***'":
20 "From *** get the *** attribute and set it to '***'."
21 }
22
23 # do they want to drill phrases first
24 if len(sys.argv) == 2 and sys.argv[1] == "english":
25 PHRASE_FIRST = True
26 else:
27 PHRASE_FIRST = False
28
29 # load up the words from the website
30 for word in urlopen(WORD_URL).readlines():
31 WORDS.append(str(word.strip(), encoding="utf-8"))
32
33
34 def convert(snippet, phrase):
35 class_names = [w.capitalize() for w in
36 random.sample(WORDS, snippet.count("%%%"))]
37 other_names = random.sample(WORDS, snippet.count("***"))
38 results = []
39 param_names = []
40
41 for i in range(0, snippet.count("@@@")):
42 param_count = random.randint(1,3)
43 param_names.append(', '.join(
44 random.sample(WORDS, param_count)))
45
46 for sentence in snippet, phrase:
47 result = sentence[:]
48
49 # fake class names
50 for word in class_names:
51 result = result.replace("%%%", word, 1)
52
53 # fake other names
54 for word in other_names:
55 result = result.replace("***", word, 1)
56
57 # fake parameter lists
58 for word in param_names:
59 result = result.replace("@@@", word, 1)
60
61 results.append(result)
62
63 return results
64
65
66 # keep going until they hit CTRL-D
67 try:
68 while True:
69 snippets = list(PHRASES.keys())
70 random.shuffle(snippets)
71
72 for snippet in snippets:
73 phrase = PHRASES[snippet]
74 question, answer = convert(snippet, phrase)
75 if PHRASE_FIRST:
76 question, answer = answer, question
77
78 print(question)
79
80 input("> ")
81 print(f"ANSWER: {answer}\n\n")
82 except EOFError:
83 print("\nBye")
運行這個腳本,試著用“面向?qū)ο蟮亩陶Z”來把它翻譯成自然語言挎峦,你應(yīng)該能看到短語字典有兩種形式香追,你只用輸入正確的那個就行。
練習從自然語言到代碼
接下來你應(yīng)該選擇用“english”選項來運行這段代碼浑测,然后用相反的方式來練習:
$ python oop_test.py english
記住翅阵,這些短語在用一些廢話歪玲,學習閱讀這些代碼的一部分原因就是試著不再去給這些變量和類的名字賦予這么多意義迁央。通常當人們看到像“cork”(軟木塞)這樣的詞時,會對它的含義感到很困惑滥崩。在上述例子中岖圈,“cork”只是一個隨機選取的類的名字。別給它賦予太多含義钙皮,而是試著用我教你的方式來對待它蜂科。
讀更多代碼
你現(xiàn)在需要繼續(xù)讀更多的代碼顽决,并在這些代碼中復習你之前學過的短語。試著找到盡可能多的包含類的文件导匣,然后跟著如下要求去做:
給出每個類的名字才菠,以及其他的類從它那里繼承了什么。
在每個類下面贡定,列出它所擁有的函數(shù)以及它們的參數(shù)赋访。
列出所有它用 self 使用的屬性。
對于每個屬性缓待,給出它繼承自哪個類蚓耽。
這些練習的目的是過一遍真實的代碼,并試著把你學過的短語和它們的用法匹配和關(guān)聯(lián)起來旋炒。如果你做足了訓練步悠,你會開始看到這些匹配模式(match patterns)呼之欲出,而不再是一些你不明白的空格或字符瘫镇。
常見問題
result = sentence[:]
是干什么用的鼎兽? 這是 Python 復制一個列表的方式。它用的是列表的切片(slice)語法 [:]
铣除,能夠很快地創(chuàng)建一個從第一個元素到最后一個元素的列表切片接奈。
這個腳本好難運行! 到目前為止你應(yīng)該能夠讓它正常運行通孽。雖然它確實有幾個小地方比較煩人序宦,但是并不復雜。試著用你目前為止所學過的東西來調(diào)試它背苦。把每一行輸入進去互捌,并且確保和我的一模一樣,然后遇到不明白的地方就在網(wǎng)上查查行剂。
還是很難秕噪! 你可以這樣做。慢點敲厚宰,一個字符一個字符地敲腌巾,但是要保證準確,然后弄明白每個詞的意思铲觉。