在李笑來老師的微博里知道《the self-taught programmer》這本書,當(dāng)前還是在美亞上買的。整個閱讀的過程也是斷斷續(xù)續(xù)的,經(jīng)過了多次“從入門到放棄”;有時是讀完了,也不知道到底自己算入門了沒有;有時是讀了后面的忘了前面的知識點(diǎn),總之是沒有多少沉淀在心里。
重新再過一遍,把知識點(diǎn)再這里提下,這里提的知識點(diǎn)更多的是自己的知識盲點(diǎn)。
本書一共分為五個部分:
Part I:Introduction to Programming
Part II: Introduction to Object-Oriented Programming
Part III: Introduction to Programming Tools
Part IV: Introduction to Computer Science
Part V : Landing a Job
Part I:Introduction to Programming
注釋:#
\ slash:可換行,原則上一條語句一行
一般縮進(jìn):四個空格
Data Type:identity(location in memory),data type(str int float bool nonetype..),value
變量命名規(guī)則:以數(shù)字、字母、下劃線組成,不能有空格,數(shù)字不能做開頭,常見的有駝峰法和大小寫法
錯誤類型:syntax error 和exception
運(yùn)算符:算計--比較--邏輯 ,記得有優(yōu)先級
control structure--》conditional statements
函數(shù)名命名時最好不要含大寫字母,可以下劃線
Built-in Functions: print len str int flaot input...
???except 后面的錯誤類型有哪些?ZeroDivisionError,ValueError
docstring 書寫要全面一點(diǎn)
def add(x,y):
"""
Returns x+y 干什么的
:param x: int
:param y: int
returns int sum of x and y.
"""
returns x+y
scope:global 和??
Containers:list ,tuple ,dictionary

| Containers | iterable | mutable |
|---|---|---|
| List | √ | √ |
| tuple | √ | × |
| dictionary | √ | √ |
string: iterable ,immutable.
+號 、 * 、 upper()、lower()、capitalize()、‘’xxx {}".format("yyy")、split(‘’x') x為分隔符、join() 'x'.join('string')、strip()、sring.find('x')、index()、replace()、in、\轉(zhuǎn)移字符 \n \t '、slice--iterable[index0:index1]
LOOP
| for-loop | while-loop |
|---|---|
| 1.for i in [iterable] 2.for i,item in enumerate([iterable]) 3.for i in range(m,n) | while [expression]: |
| break--退出循環(huán);continue--退出本次循環(huán)進(jìn)入下一次循環(huán);iterable:string ,list,tuple,dictionary |
| built-in module | other module |
|---|---|
| math、random、keyword、statistics ... | if name =="main": print("hello") 開頭加這幾行會使得導(dǎo)入模塊時不會直接顯示Print的結(jié)果 |
- Files
利用os module 構(gòu)建文件路徑,來適應(yīng)不同的操作系統(tǒng)。
import os
os.path.join('users','bob','st.tx')
open一個文件,需要一個close來關(guān)閉文件;使用with-statement python會自動關(guān)閉文件
with open("st.txt", "w) as f:
f.write("hello")
II Introduction to Object-Oriented Programming
- programming paradigms :
1.過程式編程(procedural programming):一系列步驟來解決問題,每步都會改變程序的狀態(tài)。適合簡短的程序編程。由于程序的狀態(tài)都保存在全局變量中,隨著程序規(guī)模擴(kuò)大, 可能會在多個函數(shù)中使用全局變量,很難記錄都有哪些地方對一個全局變量進(jìn)行了 修改。
2.函數(shù)式編程(functional programming):消除全局狀態(tài),解決了過程式編程中出現(xiàn)的問題,不使用或不改變?nèi)譅顟B(tài)的函數(shù), 唯一使用的狀態(tài)就是傳給函數(shù)的參數(shù)。一個函數(shù)的結(jié)果通常被繼續(xù)傳給另一個函數(shù)。 因此,這些程序員通過函數(shù)之間傳遞狀態(tài),避免了全局狀態(tài)的問題,也因此消除了由此 帶來的副作用和其他問題。
3.面向?qū)ο?object-oriented)編程范式也是通過消除全局狀態(tài)來解決過程式編程引發(fā) 的問題,但并不是用函數(shù),而是用對象來保存狀態(tài)。
根據(jù)慣例,Python 中的類名都是以大寫字母開頭,且采用駝峰命名法,即如果類名由多 個單詞組成,每個單詞的第一個字母都應(yīng)該大寫,如 LikeThis,而不是用下劃線分隔(函數(shù)的命令慣例)。
面向?qū)ο缶幊逃兴拇蟾拍?封裝、抽象、多態(tài)和繼承。
encapsulation:在面向?qū)ο缶幊讨校瑢ο髮⒆兞?(狀態(tài))和方法(用來改變狀態(tài)或執(zhí)行涉及狀態(tài)的計算)集中在一個地方— 即對象本身;隱藏類的內(nèi)部數(shù)據(jù),以避免客戶端(client)代碼(即 類外部的代碼)直接進(jìn)行訪問。Python 中沒有私有變量,所有的變量都是可以公開訪問的。Python 通過另一種方法 解決了私有變量應(yīng)對的問題:使用命名約定,變量名前有下劃線。
抽象(abstraction)指的是“剝離事物的諸多特征,使其只保留最基本的特質(zhì)”的過 程。在面向?qū)ο缶幊讨校褂妙愡M(jìn)行對象建模時就會用到抽象的技巧。
多態(tài)(polymorphism)指的是“為不同的基礎(chǔ)形態(tài)(數(shù)據(jù)類型)提供相關(guān)接口的能力”。接口,指的是函數(shù)或方法。
繼承(inheritance)另一個類那里繼承方法和 變量。被繼承的類,稱為父類(parent class);繼承的類則被稱為子類(child class)。
組合 (composition)將一個對象作為變量保存在另一個對象中,可以模擬“擁 有”關(guān)系。例如,可使用組合來表達(dá)狗和其主人之間的關(guān)系(狗有主人)。
類變量:類中但在init方法之外中定義的。訪問方式與實(shí)例變量(變量名前面加 self.)的訪問方式相同。 類變量可以在不使用全局變量的情況下,在類的所有實(shí)例之間共享數(shù)據(jù)。
實(shí)例變量 類中init中方法中定義的
魔法方法
III: Introduction to Programming Tools
Bash command-line interface
一些命令:echo同print、history查看最近的命令、pwd查看當(dāng)前目錄、/表示根目錄,如果不以/開頭,則說明使用了相對路徑、cd /到根目錄、ls顯示當(dāng)前目錄中的文件、mkdir創(chuàng)建目錄、cd ~到home路徑、cd ..返回上層目錄、rmdir 刪除文件、whoami顯示當(dāng)前用戶
命令支持一個叫旗標(biāo)(flag)的概念,可以改變命令的執(zhí)行方式。旗標(biāo)對于命令來說, 是一些值為 True 或 False 的執(zhí)行選項(xiàng)。一個命令的所有旗標(biāo)默認(rèn)置為 False。
操作系統(tǒng)和很多程序都會將數(shù)據(jù)保存在隱藏文件中。隱藏文件指的是默認(rèn)不會展示 給用戶的文件,因?yàn)樾薷碾[藏文件會影響依賴這些文件的程序。隱藏文件的名稱以英文 句點(diǎn)開頭,如.hidden。在 ls 命令后加上旗標(biāo)-a(表示所有文件),即可查看隱藏文 件。touch 命令支持從命令行新建文件。
在類 UNIX 操作性系統(tǒng)中,豎直線“|”被稱為管道(pipe)??墒褂霉艿缹⒁粋€命 令的輸出,傳入另一個命令作為輸入。例如,可使用 ls 命令的輸出,
環(huán)境變量(environment variable)是保存在操作系統(tǒng)中的變量,程序可通過這些變量 獲取當(dāng)前運(yùn)行環(huán)境的相關(guān)數(shù)據(jù),如運(yùn)行程序的計算機(jī)的名稱,或運(yùn)行程序的用戶的名稱。 使用語法 export[變量名]=[變量值],即可在 Bash 中新建一個環(huán)境變量。如需在 Bash 中引用環(huán)境變量,必須在其名稱前加一個美元符號。示例如下:
export x=100
echo $x
將環(huán)境變量添加到類 UNIX 操作系統(tǒng)使用的一個隱藏文件中,可使得環(huán)境變量持久 存在。該隱藏文件位于 home 目錄下,名為.profile。使用圖形用戶界面前往 home 目錄??稍诿钚休斎?pwd ~,找到 home 目錄的絕對路徑。然后,使用文本編輯器創(chuàng) 建一個名為.profile 的文件,在第一行輸入 export x=100 并保存文件。之后,退 出并重新打開 Bash,這時就能夠打印環(huán)境變量 x 了。
可在命令前加上 sudo(superuser do 的簡稱)。sudo 可在不影響操作系統(tǒng)安全性 的前提下,讓我們以根用戶的身份執(zhí)行命令
正則表達(dá)式(regular expression):定義搜索模式的 一組字符串。
grep 命令接受兩個參數(shù):一個正則表達(dá)式和檢索正則表達(dá)式中定義模式的文件路 徑。
grep xxx zex.txt
grep -i xxx zex.txt
加上旗標(biāo)-i 來忽略大小寫;添加旗標(biāo)-o,確保只打印與傳入的模式參數(shù)相匹配的文本:
通過內(nèi)置模塊 re 在 Python 中使用正則表達(dá)式。re 模塊提供了一個叫 findall 的方法,將正則表達(dá)式和目標(biāo)文本作為參數(shù)傳入,該方法將以列表形式返回文本中與正 則表達(dá)式匹配的所有元素.
import re
l = "Beautiful is better than ugly."
matches = re.findall('Beautiful',l,re.IGNORECASE)
print(matches)
使用補(bǔ)字符號 ^ 創(chuàng)建一個正則表達(dá)式,表示只有模 式位于行的起始位置時才匹配成功;使用美元符號$來匹配結(jié)尾指定模式的文本行;在 Python 中使用補(bǔ)字符 ^ 的示例(必須傳入 re.MULITILINE 作為 findall
的第 3 個參數(shù),才能在多行文本中找到所有匹配的內(nèi)容):
在正則表達(dá)式中加入[abc],則可匹配 a、b 或 c;可使用[[:digit:]]匹配字符串中的數(shù)字:在Python 中使用\d匹配數(shù)字
星號符*可讓正則表達(dá)式支持匹配重復(fù)字符。加上星號符之后,星號前面的元素可匹 配零或多次
在正則表達(dá)式中,句號可匹配任意字符。如果在句號后加一個星號,這將讓正則表 達(dá)式匹配任意字符零或多次。也可使用句號加星號,來匹配兩個字符之間的所有內(nèi)容。正則表達(dá)式.*可匹配兩個下劃線之間(包括下劃線)的所有內(nèi)容。星號是貪 婪匹配(greedy),意味著會盡可能多地匹配文本。如果不想一直貪婪匹配,可以在星號后面加個問號,使得正則表達(dá)式變成非貪婪模 式(non-greedy)。一個非貪婪的正則表達(dá)式會盡可能少地進(jìn)行匹配。grep 并不支持非貪婪匹配,但是在 Python 中可以實(shí)現(xiàn).
可以在正則表達(dá)式中對字符進(jìn)行轉(zhuǎn)義(忽略字符的意義,直接進(jìn)行匹配)。在正 則表達(dá)式中的字符前加上一個反斜杠\即可進(jìn)行轉(zhuǎn)義
$ echo I love $ | grep \\$
package manager pip install module_name(==版本號);pip freeze查看已安裝模塊;刪除模塊pip uninstall module_name.(刪除是后面有個點(diǎn)的)
Version Control
- 在github上創(chuàng)建一個repository
- git clone [repository_name]
- 主要2件事是 pushing (將本地所做的修改更新至中央代碼倉庫)和 pulling。推送修改到中央代碼倉庫共分 3 步。1.暫存(stage)文件,告訴 Git 希望將哪 個修改過的文件推送到中央代碼倉庫。命令 git status 可以顯示項(xiàng)目之于代碼倉庫的當(dāng)前狀態(tài),方便我們決定暫存哪些 文件。該命令會把本地代碼倉庫與中央代碼倉庫中存在差異的文件打印出來。取消文件暫存后,文件以紅色字體顯示。暫存的文件顯示為綠色。要確保位于 倉庫 目錄,然 后輸入命令 git status。使用命令 git add[文件名]即可暫存文件;現(xiàn)在通過命令 git status 確認(rèn)已經(jīng)暫存了該文件,會變?yōu)榫G色 ,提交文件,即 命令 Git 記錄本地代碼倉庫所做的修改。2.可使用語法 git commit -m [信息]提交 文件。該命令將創(chuàng)建一次提交(commit):Git 保存的一個項(xiàng)目代碼版本。3.可通過命令 git push origin master,將本地的修改推送到中央代碼庫:
pulling前往中央代碼倉庫,點(diǎn)擊按鈕 Create new file,創(chuàng)建一個名為 new.py 的文件,然后 點(diǎn)擊按鈕 Commit new file 提交該文件。這個文件目前沒有在本地代碼倉庫中,因此本地 代碼倉庫落后于中央代碼倉庫的版本。我們可以使用命令 git pull origin master 更新本地代碼倉庫:
命令 git remote -v(-v 是一個常用的旗標(biāo),用來打印詳細(xì)信息)可打印本地代 碼倉庫推送和拉取代碼的目標(biāo) URL 鏈接。
使用語法 git reset[文件路徑]即可取消暫存。
可使用命令 git log 查看項(xiàng)目的提交歷史,該命令會打印出所有做過的提交
命令 git diff (git diff xxx.py )可實(shí)現(xiàn)本地代碼倉庫與中央代碼倉庫之間文件的差別對比
IV: Introduction to Computer Science
Data Structures
- Stack :LIFO
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
last = len(self.items) - 1
return self.items[last]
def size(self):
return len(self.items)
==================
stack = Stack()
for c in "Hello":
stack.push(c)
reverse = ""
for i in range(len(stack.items)):
reverse += stack.pop()
print(reverse)
- Queue:FIFO
Algorithms
算法(algorithm)是解決問題的一系列步驟.
搜索算法(search algorithm)用來在列表等數(shù)據(jù)結(jié)構(gòu)中查找信息。順序搜索(sequential search)是一種簡單的搜索算法,依次檢查數(shù)據(jù)結(jié)構(gòu)中的每個元素,判斷其是否與查找的 元素相匹配。
def ss(number_list, n):
x = False
for i in number_list:
if i == n:
x = True
break
return x
========================
number_list = range(100)
n = 100
print(ss(number_list, n))
回文詞(palindrome)指的是逆序和正序拼寫得出的單詞都相同的詞。
def palindrome(word):
word = word.lower()
return word == word[::-1]
=============================
print(palindrome("non"))
變位詞(anagram)是通過重新組合另一個單詞的字母所組成的單詞。
def anagram(w1, w2):
w1 = w1.lower()
w2 = w2.lower()
return sorted(w1) == sorted(w2)
===============================
print(anagram("god","dog"))
計算字母頻數(shù)
def count_characters(string):
count_dict = {}
for c in string:
if c in count_dict:
count_dict[c] += 1
else:
count_dict[c] = 1
print(count_dict)
==================
count_characters("I am a hero")
**遞歸式算法(recursive algorithm) **則是通過調(diào)用自身的函數(shù)來實(shí)現(xiàn)。任何可以迭代式解決的問題,都可以遞歸式地解決; 但是,有時候遞歸算法是更加優(yōu)雅的解決方案。
1.遞歸算法必須有終止條件。
2.遞歸算法必須改變自己的狀態(tài),不斷靠近終止條件。
3.遞歸算法必須遞歸地不斷調(diào)用自己。
def bottles_of_beer(bob):
""" Prints 99 Bottle
of Beer on the
Wall lyrics.
:param bob: Must
be a positive
integer.
"""
if bob < 1:
print("""No more
bottles
of beer
on the wall.
No more
bottles of
beer""")
return
tmp = bob
bob -= 1
print("""{} bottle of
beer on the
wall. {} bottles
of beer. Take one
down, pass it around, {} bottles
of beer on the wall.""".format(tmp,tmp,bob))
bottles_of_beer(bob)
============================
bottles_of_beer(99)
V : Landing a Job
幾個普遍的編程原則
- 寫代碼是最后的手段.先在網(wǎng)上檢索解決辦法,只有在確定沒人解決過該問題之后,才開始自己動手解決。
- 正交性(Orthogonality)。在設(shè)計優(yōu)良的系 統(tǒng)中,數(shù)據(jù)庫代碼與用戶界面之間是正交的;調(diào)整用戶界面不會影響數(shù)據(jù)庫,替換數(shù)據(jù) 庫也不會改變用戶界面。”實(shí)踐中請牢記,“A 不應(yīng)該影響 B”
- 每個數(shù)據(jù)都只應(yīng)保存在一處
- 函數(shù)只做一件事
- 若耗費(fèi)時間過長,你的做法很可能就是錯的
- 第一次就要用最佳的方法完成
- 遵循慣例。PEP8 是一系 列編寫 Python 代碼的指南,強(qiáng)烈建議閱讀,可前往 https://www.python.org/dev/peps/ pep-0008/查看。
- 使用強(qiáng)大的 IDE
- 記錄日志,記錄日志(logging)指的是在軟件運(yùn)行時記錄數(shù)據(jù)的做法。我們可通過日志來協(xié)助 程序調(diào)試,更好地了解程序運(yùn)行時的狀態(tài)。Python 自帶了一個 logging 日志模塊,支持 在控制臺或文件中記錄日志。
10。 程序測試指的是檢查程序是否“達(dá)到了設(shè)計和開發(fā)要求,對各類輸入返回正確的結(jié) 果,功能執(zhí)行耗時在可接受范圍,可用性足夠高,可在目標(biāo)環(huán)境下安裝和運(yùn)行,并且實(shí) 現(xiàn)了相關(guān)利益方所期待的效果??稍诰W(wǎng)頁 https://docs.python.org/3/library/unittest.html 學(xué)習(xí)如何使用 Python 自帶的 unittest 模塊。 - 代碼審查。在代碼審查(code review)時,同事會閱讀你的代碼并提供反饋。
- 安全。學(xué)習(xí)編程時我們也不會去考慮安全問題。但是,在實(shí)際工作中,我們需要 對自己代碼的安全性負(fù)直接責(zé)任。非必要情況下, 務(wù)必不要在命令行使用 sudo 執(zhí)行命令;總是假設(shè)用戶的輸入是惡意的;最小化你的攻擊面積(attack surface),即黑客可 從程序中提取數(shù)據(jù)或攻擊系統(tǒng)的相關(guān)區(qū)域。通過最小化攻擊面積,可以減少程序出現(xiàn)漏 洞的可能性。最小化攻擊面積的幾種常見做法包括:避免保存敏感信息,賦予用戶最低 的訪問權(quán)限,盡可能少用第三方庫(代碼量越小、漏洞越少),剔除不再使用的功能代碼(代碼量越小、漏洞越少)等;但這還只是提升安全性的一小部分。我們應(yīng)該試著從黑 客的角度進(jìn)行思考。
更多學(xué)習(xí)資料
- 經(jīng)典書籍。有一些編程書籍是必讀書目?!冻绦騿T修煉之道》《設(shè)計模式》1《代碼大全》《編譯原理》,以及 MIT 出版社出版的《算法導(dǎo)論》均為程序員必讀書目。另外,強(qiáng)烈推薦 一個免費(fèi)的互動式算法入門教程,名為《Problem Solving with Data Structures and Algorithms》,這本書比《算法導(dǎo)論》更加容易理解。
2 在線課堂 http://theselftaughtprogrammer.io/ courses 網(wǎng)頁中列出了值得推薦的課程。
3.駭客新聞(Hacker News)是技術(shù)孵化器Y Combinator推出的一個用戶新聞分享平 臺,網(wǎng)址為 https://news.ycombinator.com,能夠幫助大家及時掌握最新的趨勢和技術(shù)。
下一步你應(yīng)該怎么做?要學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法,請前往 LeetCode 網(wǎng)站,進(jìn)行算法練習(xí),然后尋找更多的練習(xí)機(jī)會。
作者分享一 些有關(guān)如何持續(xù)提升程序員技能的思考。
- 找到導(dǎo)師
- 加深理解,編程領(lǐng)域中有一個叫“黑盒”的概念,指的是某個你在使用,但是并不了解其工作 原理的東西。剛開始編程時,對你來說一切都是黑盒。提升編程能力的一個最好的方式, 就是打開碰到的每個黑盒,努力掌握其原理。
- 盡可能多花時間閱讀其他人的代碼。
尼爾·科伊勒的《The Talent Code》提升了我的編程能力,因?yàn)樗虝宋艺莆杖魏我粋€技能所需要的方法論。時刻注意編程領(lǐng)域之外的動態(tài),注重吸收那些有助于編程的知識。