黑客余弦先生在知道创宇的知道创宇研发技能表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
www.shiyanlou.com
https://www.shiyanlou.com/paths/python