黑客余弦先生在知道創宇的知道創宇研發技能表v3.1中提到了入門Python的一本好書《Learn Python the Hard Way(英文版鏈接)》。其中的代碼全部是2.7版本。
如果你覺得英文版看着累,當當網有中文版,也有電子版可以選擇。
我試着將其中的代碼更新到Python 3。同時附上一些自己的初學體會,希望會對你有幫助。
中文版有人把書名翻譯為《笨辦法學python》,其實我覺得叫做《學Python,不走尋常路》更有意思些。
作者的意思你可以在序言中詳細了解。務必多讀幾遍。務必多讀幾遍。務必多讀幾遍。
【編程的思維模式】
程序就是根據輸入、經過一定的處理后,做出合適的輸出。
這個處理過程,其實就是根據輸入來做決定。想一想,人工智能。也就是利用各種輸入、各種算法來做出最恰當的決定,予以輸出。
ex0:自己准備程序環境。Windows前往官網安裝即可。
ex1: 學會Print,注意print語句在python3中必須加括號。引號必須是英文的。注意“”和""的區別
print("Hello World")
print("Hello Again")
延伸閱讀:
https://docs.python.org/3/whatsnew/3.0.html
https://wiki.python.org/moin/Python2orPython3
http://www.cnblogs.com/codingmylife/archive/2010/06/06/1752807.html
ex2:學會注釋
使用#符號來為你的程序添加注釋。注釋語句 后面任何的內容都不會被執行。注意print語句不要忘記python3的寫法。
ex3:數字和簡單數學公式
加減乘除和一般的程序都一樣。+ - * /
記得要用英文輸入法。
%這里是指求余。5 % 2余數為1
9 % 3的余數為0
另外一個要注意的是表達式的邏輯判斷。print(3+2 < 5-7)
看一下返回值,False。首字母大寫
ex4:變量和名稱
注意print中間加入了變量名。請繼續保持對python3中print語句寫法的留意。直到你已經不需要提醒。
cars = 100
print ("There are", cars, "cars available")
本節作者還提到了整型和浮點型數值的區別。
好的編程書寫習慣。對比x=100和 x = 100(注意空格)
百度搜索pep8可以看到更多資料。
ex5:更多變量和打印相關知識
my_name = "Albert Hao"
my_age = 38 # not a lie
print ("Let's talk about %s." % my_name) #注意括號的位置,% 這里是指替換雙引號里面內容的意思,注意本句和下句%s和%d
print ("He's %d years old." % my_age)
本節作者還介紹了round函數,可以在ide中學習。
print (round(1.7333,2))
看一下結果吧。
思考一下:%r的意思是什么?和%d和%s的區別。
ex6:字符串和文本
binary = "binary"
do_not = "don't"
y = "Those who know %s and those who %s." % (binary, do_not) #多個變量時,要加括號(parenthesis)
print (y)
hilarious = False #注意首字母大寫
joke_evaluation = "Isn't that joke so funny?! %r"
print (joke_evaluation % hilarious)
w = "This is the left side of ......"
e = "a string with a right side."
print (w+e)
# False is not equal to false
# % y must follow the string ahead of it.
ex7: 更多關於打印的知識
print ("Mary had a little lamb.") #在ide里面輸入print可以看到print不帶回車的參數
print ("." * 10) # 字符串也可以做乘法,把小數點改為_試一下,可以輸出一行下划線
end1 = "H"
end2 = "i"
end3 = "!"
print (end1 + end2 + end3)
print (end1,end2,end3,end=" ")
print (end1,end2,end3,end=" \n") #如果用sublime3,觀察finished in 0.2s的位置
ex8:更多打印
理解%r以及formatter作為參數傳入。
formatter = "%r %r %r %r"
print (formatter % (1,2,3,4))
print (formatter % ("one","two","three","four"))
print (formatter % (True, False, True, False))
print (formatter % (formatter,formatter,formatter,formatter))
print (formatter % (
'I had this thing.',
"That you coud type up right.",
"But it didn't sing.",
"So I said goodnight."))
ex9:打印,打印,打印
這一節主要講了 \n 的用法,這個是回車換行符。
三個引號,是指允許段內換行。"""
days = "Mon Tue Wed Thu Fri Sat Sun"
months = "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug"
print ("Here are the days:",days)
print ("Here are the months:",months)
print ("""
There's something going on here.
With the three double-quotes
We'll be able to type as much as we like.
Even 4 lines if we want, or 5, or 6.
""")
ex10:那是什么
這一節主要講了類似\n的特殊字符。
轉義符\,如果你想要輸出\,那么你必須在程序里面寫為 \\ 。
類似的特殊字符有:
\t tab鍵
\" 輸出引號
tabby_cat = "\tI'm tabbed in."
persian_cat = "I'm split\non a line."
backslash_cat = "I'm \\ a \\ cat."
fat_cat = '''
I'll do a list:
\t* Cat food
\t* Fishies
\t* Catnip\n\t* Grass
'''
print ("%s" % tabby_cat)
print (persian_cat)
print (backslash_cat)
print (fat_cat)
那段循環代碼用下面這個試一下:
while True:
for i in ["/","-","|","\\","|"]:
print("%s" % i,end="") #原文中是%s\r,我把\r換掉了,后面加了end =""
注意while和for所在的那一行結尾都要有冒號
同時下一行要有四個空格作為縮進,英文即indent。
注意這里循環是沒有執行結束語句的,所以可以手動結束。ctrl+z
新手可以試一下這個版本:
count = 0 #計數器
while count <500: #如果不超過500,就執行下面的命令
for i in ["/","-","|","\\","|"]: #方括號里面是list對象。這一行的意思是i依次取后面方括號的每一個元素。你可以換做其他符號試一試
count= count +1
print("%s" % i,end="")
ex11:讓計算機向人提問
這一章中開始有input了,這個語句就是計算機以命令行形式接受輸入的語句。
這個語句也是Python2和3的一個區別。Python3 中沒有raw_input。
print ("How old are you? ")
age = input()
print ("How tall are you? ")
height = input()
print("How much do you weigh? ")
weight = input()
print("So, you're %r old, %r tall and %r heavy," % (
age,height,weight))
原文中在print語句結尾使用逗號,以便不換行。在Python3中你可以參考ex10中循環語句里面的print的寫法,你也可以在IDLE集成環境中測試。
你打出 print ( 時,它就會提醒你了。你也可以在命令行中輸入help(print)
ex12: 用計算機向人們提問
和上一節不同之處,在於本節直接在input中提示用戶輸入並將input的結果存在變量里。
age = input("How old are you? ")
height = input("How tall are you? ")
weight = input("How much do you weigh? ")
print ("So, you're %r old, %r tall and %r heavy." % (
age, height, weight))
#注意換行的空格不能省略
在命令行下面可以輸入python -m pydoc input來查看input命令的幫助文件。
ex13:參數,接收參數,變量
本節利用了import命令導入了argv模塊。主要是在命令行中輸入參數。你需要在命令行中(windows就是cmd中),使用python ex13.py first second third類似的命令看一下程序效果。
from sys import argv
script, first, second, third = argv
print ("The script is called:", script)
print ("Your first variable is:", first)
print ("Your second variable is:", second)
print ("Your third variable is:", third)
ex14:使用提示符輸入和傳遞參數
本節將上兩節的內容結合起來。記得要用命令行傳遞user_name參數。
from sys import argv
script, user_name = argv
prompt = '> '
print ("Hi %s, I'm the %s script." % (user_name, script))
print ("I'd like to ask you a few questions.")
print ("Do you like me %s?" % user_name)
likes = input(prompt)
print ("Where do you live %s?" % user_name)
lives = input(prompt)
print ("What kind of computer do you have?")
computer = input(prompt)
print ("""
Alright, so you said %r about liking me.
You live in %r. Not sure where that is.
And you have a %r computer. Nice.
""" % (likes, lives, computer))
還記得三個引號的作用嗎?三個引號就是可以段內換行。
ex15:讀取文件
本節練習讀取文本文件。你需要提前准備一個ex15_sample.txt
作者用的內容是:
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
ex15.py的內容
from sys import argv
script, filename = argv
txt = open(filename)
print ("Here's your file %r:" % filename)
print (txt.read())
txt.close()
print ("Type the filename again:")
file_again = input("> ")
txt_again = open(file_again)
print (txt_again.read())
本節你還可以鍛煉如下能力:
在每一行上方用英語描述一下這一行的功能;你可以問其他人,也可以上網查詢,例如使用python open來檢索open命令相關的內容。
ex16:讀寫文件
這一課主要學習讀寫文件操作。如果你不懂哪一行代碼,可以自己加注釋。
注意這一課仍要通過命令行向程序傳遞參數。這一課的練習,你可以試一試將target.write那里的代碼壓縮到一行來寫。
from sys import argv
script, filename = argv
print ("We're going to erase %r." % filename)
print ("If you don't want that, hit CTRL-C (^C).")
print ("If you do want that, hit RETURN.")
input("?")
print ("Opening the file...")
target = open(filename, 'w')
print ("Truncating the file. Goodbye!")
target.truncate()
print ("Now I'm going to ask you for three lines.")
line1 = input("line 1: ")
line2 = input("line 2: ")
line3 = input("line 3: ")
print ("I'm going to write these to the file.")
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
print ("And finally, we close it.")
target.close()
ex17:更多文件操作
這一節介紹了一個新的module:exists。書里面cat test.txt,在windows里面可以在cmd命令框里面輸入type test.txt。
你可以利用python -m pydoc import來了解更多關於import的用法。
小技巧:
1、如果代碼很長,你可以分段調試代碼。
2、可以利用print變量,來分段輸出中間結果,來達到調試代碼的效果。
3、想一下,為什么要用close方法關閉文檔?如果有10萬個人,每個人都不關閉文檔,會有什么后果?編程時,從開始就要養成良好的習慣。
4、len()函數如何使用?
from sys import argv
from os.path import exists
script, from_file, to_file = argv
print ("Copying from %s to %s" % (from_file, to_file))
# we could do these two on one line too, how?
in_file = open(from_file)
indata = in_file.read()
print ("The input file is %d bytes long" % len(indata))
print ("Does the output file exist? %r" % exists(to_file))
print ("Ready, hit RETURN to continue, CTRL-C to abort.")
input()
out_file = open(to_file, 'w')
out_file.write(indata)
print ("Alright, all done.")
out_file.close()
in_file.close()
ex18:名稱,變量,代碼,函數
# this one is like your scripts with argv
def print_two(*args):
arg1, arg2 = args #注意4個空格,復制時有時候空格會丟失
print ("arg1: %r, arg2: %r" % (arg1, arg2))
# ok, that *args is actually pointless, we can just do this
def print_two_again(arg1, arg2):
print ("arg1: %r, arg2: %r" % (arg1, arg2))
# this just takes one argument
def print_one(arg1):
print ("arg1: %r" % arg1)
# this one takes no arguments
def print_none():
print ("I got nothin'.")
print_two("Zed","Shaw")
print_two_again("Zed","Shaw")
print_one("First!")
print_none()
Functions do three things:函數做了三件事,命名代碼、接收參數、構造你自己的代碼。
1. They name pieces of code the way variables name strings and numbers.
2. They take arguments the way your scripts take argv.
3. Using #1 and #2 they let you make your own "mini scripts" or "tiny commands".
Write out a function checklist for later exercises.
Write these on an index card and keep it by you while you complete the rest of these exercises or until you feel you do not need it:
1. Did you start your function definition with def?
2. Does your function name have only characters and _ (underscore) characters?
3. Did you put an open parenthesis ( right after the function name?
4. Did you put your arguments after the parenthesis ( separated by commas?
5. Did you make each argument unique (meaning no duplicated names).
6. Did you put a close parenthesis and a colon ): after the arguments?
7. Did you indent all lines of code you want in the function 4 spaces? No more, no less.
8. Did you "end" your function by going back to writing with no indent (dedenting we call it)?
And when you run ("use" or "call") a function, check these things:
1. Did you call/use/run this function by typing its name?
2. Did you put ( character after the name to run it?
3. Did you put the values you want into the parenthesis separated by commas?
4. Did you end the function call with a ) character?
Use these two checklists on the remaining lessons until you do not need them anymore.
ex19 函數和變量
本節主要測試了各種向函數傳遞參數的方法,包括直接使用數字,使用變量,使用數學公式,或者使用變量和數學公式。
def cheese_and_crackers(cheese_count, boxes_of_crackers):
print ("You have %d cheeses!" % cheese_count)
print ("You have %d boxes of crackers!" % boxes_of_crackers)
print ("Man that's enough for a party!")
print ("Get a blanket.\n")
print ("We can just give the function numbers directly:")
cheese_and_crackers(20, 30)
print ("OR, we can use variables from our script:")
amount_of_cheese = 10
amount_of_crackers = 50
cheese_and_crackers(amount_of_cheese, amount_of_crackers)
print ("We can even do math inside too:")
cheese_and_crackers(10 + 20, 5 + 6)
print ("And we can combine the two, variables and math:")
cheese_and_crackers(amount_of_cheese + 100, amount_of_crackers + 1000)
嘗試寫一個自己的函數,用10種不同的方式來運行它。
你可以通過添加注釋來逐行看懂一個程序,也可以通過大聲讀出代碼來學習它。還可以通過畫圖來學習。
函數的參數個數是否有限制?
函數可以調用函數嗎?
ex20:函數和文件
本節介紹通過函數操作文件,主要是讀取一個文件。你需要准備一個文本文件,例如ex20.txt,然后寫三行文字。執行和前面的一樣,需要在命令行里面,輸入python ex20.py ex20.txt
下面代碼中,如果復制后,空格沒有了,你要自己手動加上。(例如下面的第四行前面有4個空格)
from sys import argv
script, input_file = argv
def print_all(f):
print (f.read())
def rewind(f):
f.seek(0)
def print_a_line(line_count, f):
print (line_count, f.readline())
current_file = open(input_file)
print ("First let's print the whole file:\n")
print_all(current_file)
print ("Now let's rewind, kind of like a tape.")
rewind(current_file) #將文件指針移回文件頭
print ("Let's print three lines:")
current_line = 1
print_a_line(current_line, current_file)
current_line = current_line + 1
print_a_line(current_line, current_file)
current_line = current_line + 1
print_a_line(current_line, current_file)
其他知識:x = x + y is the same as x += y.
ex21: 可以返回值的函數
本節學習可以返回值的函數。主要是用return返回。
def add(a, b):
print ("ADDING %d + %d" % (a, b))
return a + b
def subtract(a, b):
print ("SUBTRACTING %d - %d" % (a, b))
return a - b
def multiply(a, b):
print ("MULTIPLYING %d * %d" % (a, b))
return a * b
def divide(a, b):
print ("DIVIDING %d / %d" % (a, b))
return a / b
print ("Let's do some math with just functions!")
age = add(30, 5)
height = subtract(78, 4)
weight = multiply(90, 2)
iq = divide(100, 2)
print ("Age: %d, Height: %d, Weight: %d, IQ: %d" % (age, height, weight, iq))
# A puzzle for the extra credit, type it in anyway.
print ("Here is a puzzle.")
#看一下下面這一行,如果用算術式寫出來,是什么樣的?
what = add(age, subtract(height, multiply(weight, divide(iq, 2))))
#如果要計算這個呢?24 + 34 / 100 - 1023
print ("That becomes: ", what, "Can you do it by hand?")
ex22:截止目前你都學到了什么?
今天這一課沒有代碼練習。你需要回顧前面所學過的所有內容(字符串或記號)。如果有暫時不懂的字符串或記號,找一張紙記下來。
從本書或互聯網上學習,並搞懂他們,然后記憶下來。
有一點非常重要的提醒你:
The most important thing when doing this exercise is: "There is no failure, only trying."
建議你做這個練習時,每次不要超過15分鍾。休息一會接着做。
ex23:讀一些代碼
如果前面訓練的是你寫代碼、調試代碼的能力,那么這一節訓練的就是你讀代碼的能力。
主要是以下三方面的能力:
1. Finding Python source code for things you need. 尋找你需要的Python代碼。
2. Reading through the code and looking for files. 通讀所有代碼並在文件中找到合適的代碼。
3. Trying to understand code you find. 嘗試理解你找到的代碼。
下面是你要做的:
Here's what you do:
1. Go to bitbucket.org with your favorite web browser and search for "python". 去bitbucket.org查找“Python”代碼
2. Avoid any project with "Python 3" mentioned. That'll only confuse you. 原文因為使用的Python2,所以作者提到避免Python3的代碼,但是你用的是Python3,那么就找找Python3編寫的代碼吧
3. Pick a random project and click on it. 隨機選擇一個項目
4. Click on the Source tab and browse through the list of files and directories until you find a .py file (but not
setup.py, that's useless). 選擇源代碼頁,找到.py文件,注意不是setup.py,那個文件沒有用
5. Start at the top and read through it, taking notes on what you think it does. 通讀一遍代碼
6. If any symbols or strange words seem to interest you, write them down to research later. 如果你有感興趣的符號或代碼,寫下來以后研究。
更多查看代碼的站點:
github.com
launchpad.net
koders.com
注意在https://learnpythonthehardway.org/python3/ex23.html中作者重點介紹了編碼格式,不過貌似有些復雜,先放一放稍后再看。
ex24:更多練習
這一節主要是鍛煉你的耐力和毅力。你也可以運用前面所有所學的來調試這段程序。
print ("Let's practice everything.")
print ("You\'d need to know \'bout escapes with \\ that do \n newlines and \t tabs.")
poem = """
\tThe lovely world
with logic so firmly planted
cannot discern \n the needs of love
nor comprehend passion from intuition
and requires an explanation
\n\t\twhere there is none.
"""
print("--------------")
print(poem)
print("--------------")
five = 10 - 2 + 3 - 6
print("This should be five: %s" % five)
def secret_formula(started):
jelly_beans = started * 500
jars = jelly_beans / 1000
crates = jars / 100
return jelly_beans, jars, crates
start_point = 10000
beans, jars, crates = secret_formula(start_point)
print("With a starting point of: %d" % start_point)
print("We'd have %d beans, %d jars, and %d crates." % (beans, jars, crates))
start_point = start_point / 10
print ("We can also do that this way:")
print("We'd have %d beans, %d jars, and %d crates." % secret_formula(start_point))
ex25:更加多的練習
都寫了一半了,發現cnblogs里面可以直接插入代碼。還好,不算太晚。
def break_words(stuff): """This function will break up words for us.""" words = stuff.split(' ') return words def sort_words(words): """Sorts the words.""" return sorted(words) def print_first_word(words): """Prints the first word after popping it off.""" word = words.pop(0) print (word) def print_last_word(words): """Prints the last word after popping it off.""" word = words.pop(-1) print (word) def sort_sentence(sentence): """Takes in a full sentence and returns the sorted words.""" words = break_words(sentence) return sort_words(words) def print_first_and_last(sentence): """Prints the first and last words of the sentence.""" words = break_words(sentence) print_first_word(words) print_last_word(words) def print_first_and_last_sorted(sentence): """Sorts the words then prints the first and last one.""" words = sort_sentence(sentence) print_first_word(words)
調試這段代碼需要在命令行中執行。將ex25作為模塊導入,然后引用函數。具體請參考網頁。
可以學習作者是如何分析這段代碼的執行過程。
試一下help(ex25)、help(ex25.break_words),看看輸出的內容是哪里來的?是不是ex25中三個引號后面的內容。
這一課的字符串操作命令要好好看看。可以自己定義字符串,然后再命令行格式里面調試。其中的pop好像出棧操作。
ex26:恭喜你,來做個測試
好的程序員假定自己的程序可能會出錯,然后嘗試各種可能性去修復它。這一課就請你像一個好的程序員一樣,修復每一處錯誤,讓這一段代碼越來越好,直到代碼可以完美運行。
如果遇到困難,停下來休息一會,然后接着來。
告訴你個好消息,這一課,你可以直接復制代碼。不用一行行的敲了。你可以嘗試把它變為Python3下可以執行的代碼。
這一課我們要來嘗試修補一個“壞”程序員的代碼。壞程序員很無理,傲慢,認為自己的代碼很完美,不為別人考慮。
常見的錯誤有:
定義函數時忘記輸入冒號;單詞拼寫錯誤,例如poop、returen、pirnt,=和==誤用,下划線和短橫線混用,錯誤的縮進。
def break_words(stuff): """This function will break up words for us.""" words = stuff.split(' ') return words def sort_words(words): """Sorts the words.""" return sorted(words) def print_first_word(words): """Prints the first word after popping it off.""" word = words.pop(0) print (word) def print_last_word(words): """Prints the last word after popping it off.""" word = words.pop(-1) print (word) def sort_sentence(sentence): """Takes in a full sentence and returns the sorted words.""" words = break_words(sentence) return sort_words(words) def print_first_and_last(sentence): """Prints the first and last words of the sentence.""" words = break_words(sentence) print_first_word(words) print_last_word(words) def print_first_and_last_sorted(sentence): """Sorts the words then prints the first and last one.""" words = sort_sentence(sentence) print_first_word(words) print_last_word(words) print ("Let's practice everything.") print ('You\'d need to know \'bout escapes with \\ that do \n newlines and \t tabs.') poem = """ \tThe lovely world with logic so firmly planted cannot discern \n the needs of love nor comprehend passion from intuition and requires an explantion \n\t\twhere there is none. """ print ("--------------") print (poem) print ("--------------") five = 10 - 2 + 3 - 5 print ("This should be five: %s" % five) def secret_formula(started): jelly_beans = started * 500 jars = jelly_beans / 1000 crates = jars / 100 return jelly_beans, jars, crates start_point = 10000 beans, jars, crates = secret_formula(start_point) print ("With a starting point of: %d" % start_point) print ("We'd have %d jeans, %d jars, and %d crates." % (beans, jars, crates)) start_point = start_point / 10 print ("We can also do that this way:") print ("We'd have %d beans, %d jars, and %d crabapples." % secret_formula(start_point)) sentence = "All god\tthings come to those who weight." words = break_words(sentence) sorted_words = sort_words(words) print_first_word(words) print_last_word(words) print_first_word(sorted_words) print_last_word(sorted_words) sorted_words = sort_sentence(sentence) print (sorted_words) print_first_and_last(sentence) print_first_and_last_sorted(sentence)
ex27:記住邏輯運算符
從這一課起,你就要學習計算機的邏輯運算了。如果你是初學者,建議你花費一整周來學習。不建議花更多時間,因為隨着后續學習,你自然會更熟練。
All that work memorizing the basics pays off big later.
Do a tiny bit at a time throughout the day and mark down what you need to work on most.
常見邏輯運算符及術語:
and
or
not
!= (not equal)
== (equal)
>= (greater-than-equal)
<= (less-than-equal)
True
False
你可以自己將上述運算符來組合測試。
例如not False,True or False,not (False or True)、0 != 0來試試說出它的結果。當然你也可以在命令行下面驗證一下。
你可以做成卡片,來每天試一試。記住,在這里沒有失敗,你只需要不斷的嘗試就可以了。熟能生巧。
ex28:邏輯表達式練習
這一節給出了20道練習題,你可以自己試一試,和上一節類似,可以到Python命令行中進行測試。
作者給出了六個步驟來幫助你完成題目
- Find an equality test (== or !=) and replace it with its truth. 找到==或者!=,然后用真值替換。
- Find each and/or inside parentheses and solve those first. 先找到括號里的and和or,然后用真值替換
- Find each not and invert it. 找到每個not,然后將值反轉。
- Find any remaining and/or and solve it. 找到其余的and和or,解出來。
- When you are done you should have True or False. 當上述步驟結束了,你就有了真或假的值了
注意False和True的第一個字母必須大寫。
ex29: What If 判斷語句
本節開始講解IF條件判斷語句。注意冒號,注意縮進,注意==和+=的含義。你可以變換一下people,cats,dogs的初始值,看看程序執行有何變化。
people = 20 cats = 30 dogs = 15 if people < cats: print ("Too many cats! The world is doomed!") if people > cats: print ("Not many cats! The world is saved!") if people < dogs: print ("Too many dogs! The world is drooled on!") if people > dogs: print ("The world is dry!") dogs += 5 if people >= dogs: print ("People are greater than or equal to dogs.") if people <= dogs: print ("People are less than or equal to dogs!") if people == dogs: print ("People are dogs.")
ex30:else和 If語句
本節作者先復習了上一節的幾個問題,你可以對比下看看和你想的一樣嗎?
people = 30 cars = 40 buses = 15 if cars> people: print("We should take the cars.") elif cars <people: print("We should not take the cars.") else: print("We can't decide.") if buses> cars: print("That's too many buses.") elif buses <cars: print("Maybe we could take the buses.") else: print("We still can't decide.") if people > buses: print("Alright, let's just take the buses.") else: print("Fine. Let's stay home then.")
ex31:做決定
你可以在本節使用if嵌套。就是IF里面繼續使用if分支。注意合適的縮進。你可以按照類似的思路來自己嘗試編寫小游戲。
print("You enter a dark room with two doors. Do you go through door #1 or door #2?") door = input("> ") if door == "1": print("There's a giant bear here eating a cheese cake. What do you do?") print("1. Take the cake.") print("2. Scream at the bear.") bear = input("> ") if bear == "1": print("The bear eats your face off. Good job!") elif bear == "2": print("The bear eats your legs off. Good job!") else: print("Well, doing %s is probably better. Bear runs away." % bear) elif door =="2": print("You stare into the endless abyss at Cthulhu's retina.") print("1. Blueberries.") print("2. Yellow jacket clothespins.") print("3. Understanding revolvers yelling melodies.") insanity = input("> ") if insanity == "1" or insanity == "2": print("Your body survives powered by a mind of jello. Good job!") else: print("The insanity rots your eyes into a pool of muck. Good job!") else: print("You stumbles around and fall on a knife and die. Good job!")
ex32:列表和循環
除了判斷,計算機還擅長做重復的事情。下面的代碼請主要觀察循環部分是如何寫的。
查一下list的知識;看一下elements.append()外還有什么。在IDLE中可以輸入list名稱,后面加小數點,然后按shift看看。
the_count = [1, 2, 3, 4, 5] fruits = ['apples', 'oranges', 'pears', 'apricots'] change = [1, 'pennies', 2, 'dimes', 3, 'quarters'] # this first kind of for-loop goes through a list for number in the_count: print ("This is count %d" % number) # same as above for fruit in fruits: print ("A fruit of type: %s" % fruit) # also we can go through mixed lists too # notice we have to use %r since we don't know what's in it for i in change: print ("I got %r" % i) # we can also build lists, first start with an empty one elements = [] # then use the range function to do 0 to 5 counts for i in range(0, 6): print ("Adding %d to the list." % i) # append is a function that lists understand elements.append(i) # now we can print them out too for i in elements: print ("Element was: %d" % i)
ex33:while循環
思考一下,為什么我們需要While循環?
使用While循環的注意事項:
To avoid these problems, there's some rules to follow:為了避免while循環一直執行,請遵循以下規則:
1. Make sure that you use while-loops sparingly. Usually a for-loop is better.盡量節制使用while循環,通常使用for循環會更好些。
2. Review your while statements and make sure that the thing you are testing will become False at some point.檢查你的while語句,確保它的確會在某些時候是“假”。
3. When in doubt, print out your test variable at the top and bottom of the while-loop to see what it's doing.如果對代碼有疑問,可以在wihle循環的起始和結尾都打印出測試變量來看看代碼是如何執行的。
i = 0 numbers = [] while i < 6: print ("At the top i is %d" % i) numbers.append(i) i = i + 1 print ("Numbers now: ", numbers) print ("At the bottom i is %d" % i) print ("The numbers: ") for num in numbers: print (num)
Study Drills 答案:將代碼改為函數
def make_list(ran,step): i = 1 numbers = [] ran1=range(1, ran) for i in ran1: print("At the top i is %d" % i) numbers.append(i) print("Numbers now:", numbers) print("At the bottom i is %d" % i) return numbers numbers=make_list(6,1)# first argv is range, second argv is step. print("The numbers:") for num in numbers: print(num)
使用for循環來實現相同功能:
i = 0 numbers = [] for i in range(0,6): print ("At the top i is %d" % i) numbers.append(i) i = i + 1 print ("Numbers now: ", numbers) print ("At the bottom i is %d" % i) print ("The numbers: ") for num in numbers: print (num)
ex34:如何使用列表元素
"ordinal" numbers 序數詞 第一、第二
"cardinal" number 基數詞 一、二
So, how does this help you work with lists? Simple, every time you say to yourself, "I want the 3rd animal," you translate this "ordinal" number to a "cardinal" number by subtracting 1. The "3rd" animal is at index 2 and is the penguin. You have to do this because you have spent your whole life using ordinal numbers, and now you have to think in cardinal.
Just subtract 1 and you will be good.
Remember:
ordinal == ordered, 1st;
cardinal == cards at random, 0.
小練習:
animals = ['bear', 'python', 'peacock', 'kangaroo', 'whale', 'platypus']
"The animal at 0 is the 1st animal and is a bear."
"The animal at 2 is the 3rd animal and is a peacock."
ex35:分支和函數
這一節編寫了一段游戲,請你讀一讀代碼,並畫出游戲的地圖。試着調試你的代碼,並記錄下你的錯誤,包括拼寫錯誤。
如果你有不懂的代碼,用前面所學的,在代碼前面加注釋。
from sys import exit def gold_room(): print ("This room is full of gold. How much do you take?") next = input("> ") if "0" in next or "1" in next: how_much = int(next) else: dead("Man, learn to type a number.") if how_much < 50: print ("Nice, you're not greedy, you win!") exit(0) else: dead("You greedy bastard!") def bear_room(): print ("There is a bear here.") print ("The bear has a bunch of honey.") print ("The fat bear is in front of another door.") print ("How are you going to move the bear?") bear_moved = False while True: next = input("> ") if next == "take honey": dead("The bear looks at you then slaps your face off.") elif next == "taunt bear" and not bear_moved: print("The bear has moved from the door. You can go through it now.") bear_moved = True elif next == "taunt bear" and bear_moved: dead("The bear gets pissed off and chews your leg off.") elif next == "open door" and bear_moved: gold_room() else: print ("I got no idea what that means.") def cthulhu_room(): print ("Here you see the great evil Cthulhu.") print ("He, it, whatever stares at you and you go insane.") print ("Do you flee for your life or eat your head?") next = input("> ") if "flee" in next: start() elif "head" in next: dead("Well that was tasty!") else: cthulhu_room() def dead(why): print (why, "Good job!") exit(0) def start(): print ("You are in a dark room.") print ("There is a door to your right and left.") print ("Which one do you take?") next = input("> ") if next == "left": bear_room() elif next == "right": cthulhu_room() else: dead("You stumble around the room until you starve.") start()
ex36:設計和調試
本節提到了設計和調試IF和For循環的規則。
Rules For If-Statements IF語句的規則
1. Every if-statement must have an else. 每個If語句必須有else語句。
2. If this else should never be run because it doesn't make sense, then you must use a die function in the else that prints out an error message and dies, just like we did in the last exercise. This will find many errors.
如果else語句因為沒有意義永遠不會執行,你需要使用die函數來打印錯誤信息,就像上一節練習中的代碼。
3. Never nest if-statements more than 2 deep and always try to do them 1 deep. This means if you put an if in
an if then you should be looking to move that second if into another function.
不要嵌套超過兩級if,也就是說你要是在if里面嵌套了一個if,那么最好將第二個if移到另一個函數。
4. Treat if-statements like paragraphs, where each if,elif,else grouping is like a set of sentences. Put blank lines before and after.
把每一個if語句寫成一段,if,elif,else都寫成一句話。每一個If語句段落前后都加上空行。
5. Your boolean tests should be simple. If they are complex, move their calculations to variables earlier in your function and use a good name for the variable.
你的IF語句測試條件應該簡單。如果它們很復雜,將它們用變量提前定義好並給它起個有意義的變量名。
上述規則你可以結合上一節的例子,加深理解。
Rules For Loops 循環語句的規則
1. Use a while-loop only to loop forever, and that means probably never. This only applies to Python, other languages are different.只有在想永遠循環的時候使用while語句。這也意味着幾乎是“永遠不要”使用。當然這只是對Python,其他語言可能會不一樣。
2. Use a for-loop for all other kinds of looping, especially if there is a fixed or limited number of things to loop over.在其他情況都是用for循環語句。特別是只有固定的或者有限個數的變量時。
Tips For Debugging 調試代碼的小技巧
1. Do not use a "debugger". A debugger is like doing a full-body scan on a sick person. You do not get any specific useful information, and you find a whole lot of information that doesn't help and is just confusing.
不要使用調試器。調試器像一個對病人做的全面體檢。你不會得到具體有用的建議,你會發現很多沒有多大幫助、卻會令你困惑的建議。
2. The best way to debug a program is to use print to print out the values of variables at points in the program to see where they go wrong.
最好的調試程序的辦法是:在合適的語句點使用使用打印語句(print語句)來打印出變量的值,看看他們是不是錯誤了。
3. Make sure parts of your programs work as you work on them. Do not write massive files of code before you try to run them. Code a little, run a little, fix a little.
分段調試代碼,確保它們正確。不要一下寫很多的代碼。嘗試寫一段,運行一段,改正一段。
ex37:編程符號回顧
這一節分幾類列出了作者認為重要的內容:關鍵字、數據類型、轉義字符、字符格式符。
然后找一些代碼來學習,請按照如下步驟學習:
一、打印你想要學習的那部分代碼,每次打印一部分。
二、按照如下步驟加注釋學習:
1. Functions and what they do. 函數和它們的功能。
2. Where each variable is first given a value. 每個變量第一次賦值的位置。
3. Any variables with the same names in different parts of the program. These may be trouble later.任何不同位置、相同名稱的變量,這些可能會帶來麻煩。
4. Any if-statements without else clauses. Are they right? 任何沒有else語句的IF語句。它們對嗎?
5. Any while-loops that might not end. 任何可能無法終止的while循環。
6. Finally, any parts of code that you can't understand for whatever reason. 最后,任何你無法理解的代碼。
三、利用注釋將代碼解釋給你自己。把函數解釋一下:他們有何作用,涉及哪些變量。
四、對一些難的代碼,可以逐行、逐函數的跟蹤變量。你可以將代碼再打印一份,在頁面空白處寫上追蹤變量的值。
練習:
1、學習一下流程圖,嘗試自己畫一幅。
2、如果你在學習的代碼里發現錯誤,嘗試修復並告訴作者你所做的變化。
3、如果你沒有紙,也可以在電腦上使用注釋#來完成。
ex38:學習使用“列表”
這一課作者重點介紹了lists的操作。split和pop方法。同時使用一個例子,初步引入了類,當然后面章節會深入學習。
為了說明mystuff.append('hello')的執行過程,使用的關於類的小例子:
class Thing(object): def test(hi): print ("hi") a = Thing() a.test()
下面的代碼包含列表的操作示例:
ten_things = "Apples Oranges Crows Telephone Light Sugar" print ("Wait there's not 10 things in that list, let's fix that.") stuff = ten_things.split(" ") more_stuff = ["Day","Night","Song","Frisbee","Corn","Banana","Girl","Boy"] while len(stuff) != 10: next_one = more_stuff.pop() print( "Adding: ", next_one) stuff.append(next_one) print("There's %d items now." % len(stuff)) pass print ("There we go:", stuff) print ("Let's do some things with stuff.") print (stuff[1]) print (stuff[-1]) print (stuff.pop()) print (" ".join(stuff)) print ("#".join(stuff[3:5]))
注意看列表的元素引用操作、列表的出棧操作pop、join操作。
ex39:詞典,可愛的詞典(dictionary是一種Python新的數據結構)
你只能用數字獲取list其中的元素。而dictionary允許你用除了數字以外的任意值引用類型的元素。就好比一本字典,你知道了拼音,可以去查字。
可以再IDLE中運行如下代碼:
>>> stuff = {'name': 'Zed', 'age': 36, 'height': 6*12+2} >>> print (stuff['name']) Zed >>> print (stuff['age']) 36 >>> print (stuff['height']) 74 >>> stuff['city'] = "San Francisco" >>> print (stuff['city']) San Francisco >>>
# create a mapping of state to abbreviation states = { 'Oregon': 'OR', 'Florida': 'FL', 'California': 'CA', 'New York': 'NY', 'Michigan': 'MI' } # create a basic set of states and some cities in them cities = { 'CA': 'San Francisco', 'MI': 'Detroit', 'FL': 'Jacksonville' } # add some more cities cities['NY'] = 'New York' cities['OR'] = 'Portland' # print out some cities print ('-' * 10) print ("NY State has: ", cities['NY']) print ("OR State has: ", cities['OR']) # print some states print ('-' * 10) print ("Michigan's abbreviation is: ", states['Michigan']) print ("Florida's abbreviation is: ", states['Florida']) # do it by using the state then cities dict print ('-' * 10) print ("Michigan has: ", cities[states['Michigan']]) print ("Florida has: ", cities[states['Florida']]) # print every state abbreviation print ('-' * 10) for state, abbrev in states.items(): print ("%s is abbreviated %s" % (state, abbrev)) # print every city in state print ('-' * 10) for abbrev, city in cities.items(): print ("%s has the city %s" % (abbrev, city)) # now do both at the same time print ('-' * 10) for state, abbrev in states.items(): print ("%s state is abbreviated %s and has city %s" % ( state, abbrev, cities[abbrev])) print ('-' * 10) # safely get a abbreviation by state that might not be there state = states.get('Texas', None) if not state: print ("Sorry, no Texas.") # get a city with a default value city = cities.get('TX', 'Does Not Exist') print ("The city for the state 'TX' is: %s" % city)
思考題:
1、list和dictionary的區別是什么?
A list is for an ordered list of items. A dictionary (or dict) is for matching some items (called "keys") to other items (called "values").
你可以使用help(list)、help(dict)來查詢幫助。
2、舉例說明dictionary可用於什么場景?list呢?
Any time you have to take one value, and "look up" another value. In fact you could call dictionaries "look up tables".
A list is for any sequence of things that need to go in order, and you only need to look them up by a numeric index.
3、如果我需要一個dictionary,但是同時又希望排序,該怎么做呢?(collections.OrderedDict)
ex40:模塊,類,和對象
本節用你熟悉的詞典、模塊的概念,引出了類的基本概念。
模塊就是一段代碼,單獨存放在*.py中。它和詞典類似。
In the case of the dictionary, the key is a string and the syntax is [key]. In the case of the module, the key is an identifier, and the syntax is .key. Other than that they are nearly the same thing.
類就好像模塊。
A way to think about modules is they are a specialized dictionary that can store Python code so you can get to it with the '.' operator. Python also has another construct that serves a similar purpose called a class. A class is a way to take a grouping of functions and data and place them inside a container so you can access them with the '.' (dot) operator.
對象就像小型的導入imports。也叫實例化。
ex40a.py
class MyStuff(object): def __init__(self): self.tangerine = "And now a thousand years between" def apple(self): print ("I AM CLASSY APPLES!") thing = MyStuff() thing.apple() print (thing.tangerine)
ex40b.py
class Song(object): def __init__(self, lyrics): self.lyrics = lyrics def sing_me_a_song(self): for line in self.lyrics: print (line) happy_bday = Song(["Happy birthday to you", "I don't want to get sued", "So I'll stop right there"]) bulls_on_parade = Song(["They rally around the family", "With pockets full of shells"]) happy_bday.sing_me_a_song() bulls_on_parade.sing_me_a_song()
思考題:
1、為什么在類中定義 __init__以及其他函數時,需要傳入(self)?
因為不傳入self,其中的變量就不夠明確,也不知道是指主函數還是類中的變量。
EX41:學習面向對象的語言
本節分了三方面來學習類:單詞訓練、短語訓練、兩者結合的訓練。
你可以將所有這些抄寫在卡片上,有空就拿出來記憶。
1、單詞:
class : Tell Python to make a new kind of thing.
object : Two meanings: the most basic kind of thing, and any instance of some thing.
instance : What you get when you tell Python to create a class.
def : How you define a function inside a class.
self : Inside the functions in a class, self is a variable for the instance/object being accessed.
inheritance : The concept that one class can inherit traits from another class, much like you and your parents.
composition : 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.
2、短語:
class X(Y)
"Make a class named X that is-a Y."
class X(object): def __init__(self, J)
"class X has-a __init__ that takes self and J parameters."
class X(object): def M(self, J)
"class X has-a function named M that takes self and J parameters."
foo = X()
"Set foo to an instance of class X."
foo.M(J)
"From foo get the M function, and call it with parameters self, J."
foo.K = Q
"From foo get the K attribute and set it to Q."
當然,有電腦的好處就是你可以讓程序來輔助你記憶。
import random import urllib.request import sys WORD_URL = "http://learncodethehardway.org/words.txt" WORDS = [] PHRASES = { "class ###(###):": "Make a class named ### that is-a ###.", "class ###(object):\n\tdef __init__(self,***)": "classe ### has-a __init__ that takes self and *** parameters.", "class ###(object):\n\tdef __init__(self,@@@)": "classe ### has-a function named *** that takes self and @@@ parameters.", "*** = ###()": "Set *** to an instance of class ###.", "***py.***(@@@)": "from *** get the *** function, and call it with parameters self, @@@.", "***.*** = '***'": "from *** get the *** attribute and set it to '***'." } #do they want to drill phrases first PHRASES_FIRST = False if len(sys.argv) == 2 and sys.argv[1] == "english": PHRASES_FIRST = True #load up the words from the websites for word in urllib.request.urlopen(WORD_URL).readlines(): WORDS.append(word.strip().decode("utf-8")) #這里做了一次byte到str的轉換 print(WORDS) def convert(snippet, phrase): class_names = [w.capitalize() for w in random.sample(WORDS, snippet.count("###"))] other_names = random.sample(WORDS, snippet.count("***")) results = [] param_names = [] for i in range(0, snippet.count("@@@")): param_count = random.randint(1,3) param_names.append(", ".join(random.sample(WORDS, param_count))) for sentence in snippet, phrase: result = sentence[:] #fake class names for word in class_names: result = result.replace("###", word, 1) #fake other names for word in other_names: result = result.replace("***", word, 1) #fake parameter lists for word in param_names: result = result.replace("@@@", word, 1) results.append(result) return results #keep going until they hit CTRL-D try: while True: snippets = PHRASES.keys() random.shuffle(list(snippets))#這里做了一次顯示的list轉換 for snippet in snippets: phrase = PHRASES[snippet] question, answer = convert(snippet, phrase) if PHRASES_FIRST: question, answer = answer, question print (question) input("> ") print ("ANSWER: %s\n\n" % answer) except EOFError: print("\nBye")
ex42:Is-A,Has-A,對象,和類
查詢了一下,作者自己已經有Python 3版本的書了。不過截至目前我沒有看到中譯本。20170701
https://learnpythonthehardway.org/python3
更進一步學習Python的網站:
1、http://www.pythonchallenge.com/
writeup:http://garethrees.org/2007/05/07/python-challenge/
2、https://python.swaroopch.com
A byte of python,很多學校的教材,包括斯坦福(https://mygsb.stanford.edu/sites/default/files/A Byte of Python.pdf)
3、https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences
官網教材
4、GUI編程
https://www.ibm.com/developerworks/cn/linux/sdk/python/charm-12/
可愛的 Python:Python 中的 TK編程
https://wiki.python.org/moin/GuiProgramming
https://docs.python.org/3.6/library/tkinter.html
5、Python中文手冊
http://www.pythondoc.com/pythontutorial3/inputoutput.html
6、實驗樓 Python