diff --git a/PythonThinking/task1-环境搭建与认识学习方法.md b/PythonThinking/task1-环境搭建与认识学习方法.md new file mode 100644 index 0000000..a6076be --- /dev/null +++ b/PythonThinking/task1-环境搭建与认识学习方法.md @@ -0,0 +1,69 @@ +# 前言 +课程设计是由笨方法学python和MIT 6.00课程结合改编而成,作为基础的一个课程,不涉及算法,只是基础的python语法和编程思维 +课程的目标是让0基础的同学学习后可以掌握python的基础使用,以及看懂别人写的代码并运用,以便学习更多的课程 +设计课程的原因,学习了许多datawhale的课程,感觉上缺乏一个入门的课程,因为我在学习中碰到许多问题是基础没有打好导致的,所以我找到MIT的基础计算机课程6.00,作为基础学习,以及在图书馆时找学习资料时看见笨方法学python的书,好奇是怎样的笨方法学习,于是用笨方法开始学python,发现笨方法更简单, +基础知识是采用笨方法学习法,其实是指令式学习,不采用复制黏贴的方式,针对每个代码进行复现,进步会很快,我个人觉得是很有效的学习方法,所以在这里是建议大家使用这个方法进行学习!!一起加油 + +## 笨方法学习法介绍(书中原文): +你将会做所有程序员学习一门编程语言都会做的非常简单的事情: +1. 做好每一个练习; +2. 准确敲好每一个程序; +3. 让它运行。 + +就是这样。刚开始可能会比较难,但坚持下去。如果你通读了这本书,每晚花个一两小时做做习题,你将能够为自己读下一本编程书打下良好的基础。这本书不会让你一夜之间变成程序员,但是它将会带你走上学习如何编程的道路。 + +这本书的目的是教会你作为编程新手所需的三种最重要的技能:读和写、注重细节、发现不同。 + +一、读和写 +如果你连打字都不行,那你学习编程也会成问题。尤其如果你连程序源代码中的那些奇怪字符都打不出来,就别提编程了。没有这些基本技能,你将连最基本的软件工作原理都难以学会。 + +所以,把代码示例打出来并运行,能够帮助你学习各种符号的名称、更熟练地敲出来、以及读懂编程语言。 + +二、注意细节 +区分好程序员和差程序员的一个重要标准,就是对细节的注重程度,事实上,这也是任何行业区分好坏的标准。如果缺乏对工作中每个微小细节的注意,你的工作成果将缺乏重要的元素。拿编程来讲,主意细节将会让你远离各种bug和难用的系统。 + +通过这本书的学习,以及准确打出每一个例子,你将能够训练你的大脑,在做练习的时候更多地关注细节。 + +三、发现不同 +程序员长年累月的工作会培养出一个重要技能,那就是对于不同点的区分能力。一个有经验的程序员看到两个仅有细微差别的程序,可以立即指出其中的不同。程序员还造出工具来让这件事更加容易,不过我们不会用到这些工具。你要先用笨办法训练自己,然后再用工具。 + +在你做这些练习并敲代码的时候,你一定会出错。这是不可避免的,即使有经验的程序员也会偶尔写错。你的任务是把自己写的东西和要求的正确答案对比,把所有的不同点都修正过来。这样做可以让你对程序里的错误、bug 以及其他问题更加敏感。 + +四、要问,不要盯着看 +你只要写代码,就会出现 bug。Bug 意味着你写的代码有瑕疵、有错误、或者有问题。Bug 来源于一个传说,从前有一只飞蛾飞进了第一台计算机,造成了故障。修复它就需要“debugging”。在软件世界里,有着不计其数的 bug。 + +就像第一只飞蛾,你的 bugs 将会藏在你代码的某处,你必须找到它们。你不能只是坐在电脑前盯着屏幕上的代码,希望答案能自己跳出来。这样做不会有额外的信息,你需要额外的信息来解决问题,所以你得起来寻找这只飞蛾。 + +怎么寻找呢?你需要审问你的代码,问它现在是怎么回事儿,或者从另一个不同的视角去看待这个问题。在这本书里,我将会频繁地告诉你“别盯着看,要问”。我将会向你演示如何让你的代码告诉你正在发生的一切,并且如何找到可能的解决方案。我还会教你一些从不同角度看代码的方法,让你能够获取更多信息和洞见。 + +五、不要复制粘贴 +你必须手动将每个练习打出来。复制粘贴会让这些练习变得毫无意义。这些习题的目的是训练你的双手和大脑思维,让你有能力读代码、写代码、观察代码。如果你复制粘贴,那你就是在欺骗自己,这些练习的效果也将大打折扣。 + +六、一个关于坚持练习的忠告 +在你通过这本书学习编程时,我正在学习弹吉他。我每天至少练习 2 个小时,至少花一个小时练习音阶、和声、和弦,剩下的时间用来学习音乐理论和歌曲演奏以及训练听力等。有时我一天会花 8 个小时来练习,因为我觉得这是一件有趣的事情。对我来说,重复性练习是学好一样东西最自然而然的方法。并且我深知,要掌握一件事情,只有每天坚持练习。虽然有时候,我整个人状态很差(甚至经常这样),或者觉得实在太难。没关系,坚持尝试,到最后你会发现它越来越简单,并且开始越来越有趣。 + +在我写《笨办法学 Python》和《笨办法学 Ruby》的过程中,我发现了绘画的乐趣。我在自己 39 岁的时候爱上了这门视觉艺术,并且像学习吉他、音乐和编程一样每天花时间学习画画。我收集了相关的教材,并且按照书中所说,每天坚持画,同时专注于享受这种学习过程的乐趣。我完全不是一个艺术家,甚至差得很远,但我现在至少可以说我会画画了。我学习画画的方法就跟我在这本书里教你的一样。如果你把整个问题分解为一个个小练习和课程,并且每天做,你就可以学会几乎所有的东西。如果你专注于细微的进步,并且享受学习过程,你将会从中获益,无论你最后擅长到何种程度。 + +当你通过这本书学习编程的时候,要记住任何值得做的事情一开始都是困难的。也许你是一个害怕失败的人,一碰到困难就想放弃;也许你是一个缺乏自律的人,一碰到“无聊”的事情就不想上手;也许因为有人夸你“天赋异禀”而让你自视甚高,不愿意做这些看上去很笨拙的事情,怕有负你”神童”的称号;也许你太过激进,把自己跟有 20 多年经验的编程老手相比,让自己失去了信心。 + +无论是什么原因让你想要放弃,你一定要坚持下去。如果你碰到做不出来的课后练习,或者碰到一节看不懂的练习,你可以暂时跳过去,过一阵子回来再看。只要坚持下去,你总会弄懂的,因为编程的过程中总是会出现这样的问题。 + +一开始你可能什么都看不懂。这会让你感觉很不舒服,就像学习人类的自然语言一样。你会发现很难记住一些单词和特殊符号的用法,而且会经常感到很困惑。但是突然有一天,你一下子变得豁然开朗,以前不明白的东西忽然就明白了。如果你坚持练习下去,坚持去上下求索,你最终会学会这些东西。你可能不会成为一位编程大师,但你至少会明白程序是怎么运行的。 + +如果你放弃的话,你将永远达不到那种“豁然开朗”的时刻。你会在第一次碰到不明白的东西时(一开始就是所有东西)就选择放弃。如果你坚持尝试,坚持练习下去,坚持去弄懂习题的话,你最终一定会明白其中的内容。 + +如果你学习了本课程,却还是不知道怎么编程,那也没关系,至少你试过了。你可以说你已经尽过力但成效不佳,但至少你试过了。这也是一件值得你骄傲的事情。 + + + + +# 1、Python3的使用 +初学者建议先使用阿里云天池的DSW(Data Science Workshop)进行学习,可以直接在线上进行学习,在学习一段时间后,在本地电脑上安装Python3,建议使用anaconda,已经含有很多python3的库,免去许多安装的烦恼 + + + + + + + + diff --git a/PythonThinking/task2-数学运算、字符串和文本、列表.md b/PythonThinking/task2-数学运算、字符串和文本、列表.md new file mode 100644 index 0000000..83fcd56 --- /dev/null +++ b/PythonThinking/task2-数学运算、字符串和文本、列表.md @@ -0,0 +1,228 @@ +# 2、基础 +基础部分,我会选择主要部分的进行练习,以及提供深入的练习,以及还有很多指令,大家可以自己选择感兴趣或者要用到的进行补充,这部分逻辑思想主要是让大家知道怎么进行自学 + +## (1)实现第一行代码和认识注释 +写出你的第一行代码向世界问好 + +`print('hallo world')` + +认识注释,注释是由# 加相关备注,但是不会在代码中运行,可以作为帮助理解的功能 + +```python +1 # A comment, this is so you can read your program later. +2 # Anything after the # is ignored by python. +3 +4 print("I could have code like this.") # and the comment after 5 +6 # You can also use a comment to "disable" or comment out code +7 # print("This won't run.") +8 +9 print("This will run.") +``` + + + +## (2)数学运算 + +### 认识运算符 + +加减乘除等以及特殊符号 + +• `+` plus,加号 +• `-` minus,减号 +• `/` slash,斜杠 +• `*` asterisk,星号 +• `%` percent,百分号 +• `<` less-than,小于号 +• `>` greater-than,大于号 +• `<=` less-than-equal,小于等于号 +• `>=` greater-than-equal,大于等于号 + + + +```python +1 print("I will now count my chickens:") +2 +3 print("Hens", 25 + 30 / 6) +4 print("Roosters", 100 - 25 * 3 % 4) +5 +6 print("Now I will count the eggs:") +7 +8 print(3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6) +9 +10 print("Is it true that 3 + 2 < 5 - 7?") +11 +12 print(3 + 2 < 5 - 7) +13 +14 print("What is 3 + 2?", 3 + 2) +15 print("What is 5 - 7?", 5 - 7) +16 +17 print("Oh, that's why it's False.") +18 +19 print("How about some more.") +20 +21 print("Is it greater?", 5 > -2) +22 print("Is it greater or equal?", 5 >= -2) +23 print("Is it less or equal?", 5 <= -2) +``` + +你应该会看到的结果是 + +```python +I will now count my chickens: Hens 30.0 +Roosters 97 +Now I will count the eggs: 6.75 +Is it true that 3 + 2 < 5 - 7? False +What is 3 + 2? 5 +What is 5 - 7? -2 +Oh, that's why it's False. How about some more. +Is it greater? True +Is it greater or equal? True + +Is it less or equal? False +``` + +自我练习 + +1. 在每一行上面,用 `#` 写一句注释,向自己解释这行代码的作用。 +3. 找一些你需要计算的东西,然后写一个新的 `.py` 文件。 +4. 用浮点数重新写一下`,让它更精确一些,比如 20.0 就是一个浮点数。 + +## (3)字符串和文本 + +字符如何引用 + +```python +1 cars = 100 +2 space_in_a_car = 4.0 +3 drivers = 30 +4 passengers = 90 +5 cars_not_driven = cars - drivers +6 cars_driven = drivers +7 carpool_capacity = cars_driven * space_in_a_car +8 average_passengers_per_car = passengers / cars_driven +9 +10 +11 print("There are", cars, "cars available.") +12 print("There are only", drivers, "drivers available.") +13 print("There will be", cars_not_driven, "empty cars today.") +14 print("We can transport", carpool_capacity, "people today.") +15 print("We have", passengers, "to carpool today.") +16 print("We need to put about", average_passengers_per_car, +17 "in each car.") +``` + +自己的信息引用 + +```python +1 my_name = 'Zed A. Shaw' +2 my_age = 35 # not a lie +3 my_height = 74 # inches +4 my_weight = 180 # lbs +5 my_eyes = 'Blue' +6 my_teeth = 'White' +7 my_hair = 'Brown' +8 +9 print(f"Let's talk about {my_name}.") +10 print(f"He's {my_height} inches tall.") +11 print(f"He's {my_weight} pounds heavy.") +12 print("Actually that's not too heavy.") +13 print(f"He's got {my_eyes} eyes and {my_hair} hair.") +14 print(f"His teeth are usually {my_teeth} depending on the coffee.") +15 +16 # this line is tricky, try to get it exactly right +17 total = my_age + my_height + my_weight +18 print(f"If I add {my_age}, {my_height}, and {my_weight} I get {total}.") +``` + +#### 附加练习 +尝试改成自己的信息 + +### 输入一整段字符串、变量和格式 +程序员都喜欢使用简短的缩写来节省时间,但是那些缩写在你看来会十分晦涩难懂。所以我们得尽早开始学习阅读和书写这些东西。 +```python +1 types_of_people = 10 +2 x = f"There are {types_of_people} types of people." +3 +4 binary = "binary" +5 do_not = "don't" +6 y = f"Those who know {binary} and those who {do_not}." +7 +8 print(x) +9 print(y) +10 +11 print(f"I said: {x}") +12 print(f"I also said: '{y}'") +13 +14 hilarious = False +15 joke_evaluation = "Isn't that joke so funny?! {}" +16 +17 print(joke_evaluation.format(hilarious)) +18 +19 w = "This is the left side of..." +20 e = "a string with a right side." +21 +22 print(w + e) +``` +#### 运行结果 + +```python +There are 10 types of people. +Those who know binary and those who don't. +I said: There are 10 types of people. +I also said: 'Those who know binary and those who don't.' +Isn't that joke so funny?! False +This is the left side of...a string with a right side. +``` +#### 附加练习 +1、复习一遍这个程序,并在每一行上面写上注释来解释它。 +2、找到所有把字符串放在字符串里面的地方,一共有 4 处。 +3、你确定有 4 处吗?你怎么知道?也许我爱撒谎呢。 +4、解释一下为什么把 w 和 e 两个字符串用 + 连起来能够弄成一个更长的字符串。 +### 把代码打乱 +你现在已经可以把代码打乱了。把它当成一个游戏,用一种最聪明或者最简单的方式把代码打乱。打乱之后,你需要修复它们。如果你跟你的朋友一起学习,你们可以相互打乱对方的代码,然后再试着修复它。把你的代码发给你的队友,让他们打乱,然后你再试着找出它们的错误,并修复它。记住,如果你已经写了一遍这些代码了,你可以再写一次。如果你打乱得太彻底了,就试着重新写一遍。 + +#### 常见问题 +为什么你在一些字符串外面放的是单引号,而其他的不是?大多数是因为格式。但是如果一个字符串已经用了双引号,我就会在这个字符串里面用单引号,看看第 6 行和第 15 行你就知道了。 + +如果你觉得一个笑话很好笑,可以写 hilarious = True 吗? 可以的,你会在后面学习到这些布尔值。 + + + +## (4)列表 +List(列表) 是 Python 中使用最频繁的数据类型。 + +列表可以完成大多数集合类的数据结构实现。它支持字符,数字,字符串甚至可以包含列表(即嵌套)。 + +列表用 [ ] 标识,是 python 最通用的复合数据类型。 + +列表中值的切割也可以用到变量 [头下标:尾下标] ,就可以截取相应的列表,从左到右索引默认 0 开始,从右到左索引默认 -1 开始,下标可以为空表示取到头或尾。 +```python +list = [ 'runoob', 786 , 2.23, 'john', 70.2 ] +tinylist = [123, 'john'] + +print(list) # 输出完整列表 +print(list[0]) # 输出列表的第一个元素 +print(list[1:3]) # 输出第二个至第三个元素 +print(list[2:]) # 输出从第三个开始至列表末尾的所有元素 +print(tinylist * 2) # 输出列表两次 +print(list + tinylist) # 打印组合的列表 +``` +输出结果 + +```python +['runoob', 786, 2.23, 'john', 70.2] +runoob +[786, 2.23] +[2.23, 'john', 70.2] +[123, 'john', 123, 'john'] +['runoob', 786, 2.23, 'john', 70.2, 123, 'john'] +``` + +#### 附加练习 +搜索列表的相关知识,看还有什么操作 + + + + + + diff --git a/PythonThinking/task3-字典、元组、布尔类型、读写文件.md b/PythonThinking/task3-字典、元组、布尔类型、读写文件.md new file mode 100644 index 0000000..2065402 --- /dev/null +++ b/PythonThinking/task3-字典、元组、布尔类型、读写文件.md @@ -0,0 +1,328 @@ + +## (5)字典 +现在你要学习 Python 中的另一种数据结构——字典(Dictionary)。字典(也叫 dict)是一种和列表类似的数据存储方式。但是不同于列表只能用数字获取数据,字典可以用任何东西来获取。你可以把字典当成是一个存储和组织数据的数据库。 + +让我们比较一下列表和字典的作用。你看,列表可以让你做这些事情: + +```python +>>> things = ['a', 'b', 'c', 'd'] +>>> print(things[1]) +b +>>> things[1] = 'z' +>>> print(things[1]) +z +>>> things +['a', 'z', 'c', 'd'] +``` +你可以用数字来索引列表,找到列表里面有些什么。到现在你应该能够理解这一点。但是你还要确保自己明白,你只能用数字来取出列表中的元素。 + +相比之下,字典能让你用几乎所有的东西,而不只是数字。是的,字典能够把一个东西和另一个东西关联起来,不管它们是什么类型。我们来看看: + +```python +>>> stuff = {'name': 'Zed', 'age': 39, 'height': 6 * 12 + 2} +>>> print(stuff['name']) +Zed +>>> print(stuff['age']) +39 +>>> print(stuff['height']) +74 +>>> stuff['city'] = "SF" +>>> print(stuff['city']) +SF +``` +你会看到我们用了字符串(而不是数字)来从 stuff 字典中取出了我们想要的东西。我们也可以用字符串来给字典添加新的东西。而且,也可以不用字符串,我们可以这样做: + +```python +>>> stuff[1] = "Wow" +>>> stuff[2] = "Neato" +>>> print(stuff[1]) +Wow +>>> print(stuff[2]) +Neato +``` +在这一段代码中我用了数字,所以你看,我在打印字典的时候既可以用数字也可以用字符串来作为键。我可以用任何东西。好吧,大多数东西,不过你现在就假装能够用任何东西吧。 + +当然,如果一个字典只能放东西那就太蠢了。下面是如何用 'del' 关键词来删除其中的东西: + +```python +>>> del stuff['city'] +>>> del stuff[1] +>>> del stuff[2] +>>> stuff +{'name': 'Zed', 'age': 39, 'height': 74} +``` +### 一个字典示例 + +接下来我们要做一个练习,你必须非常仔细,我要求你将这个练习写下来,然后试着弄懂它做了些什么。当你把东西放进字典、随意取出、以及做其他操作的时候记得做一下笔记。 + +注意一下这个例子是如何把州名和它们的缩写以及州的缩写和城市映射(mapping)起来的,记住,“映射”或者说“关联”(associate)是字典的核心理念。 + +```python +1 # create a mapping of state to abbreviation +2 states = { +3 'Oregon': 'OR', +4 'Florida': 'FL', +5 'California': 'CA', +6 'New York': 'NY', +7 'Michigan': 'MI' +8 } +9 +10 # create a basic set of states and some cities in them +11 cities = { +12 'CA': 'San Francisco', +13 'MI': 'Detroit', +14 'FL': 'Jacksonville' +15 } +16 +17 # add some more cities +18 cities['NY'] = 'New York' +19 cities['OR'] = 'Portland' +20 +21 # print out some cities +22 print('-' * 10) +23 print("NY State has: ", cities['NY']) +24 print("OR State has: ", cities['OR']) +25 +26 # print some states +27 print('-' * 10) +28 print("Michigan's abbreviation is: ", states['Michigan']) +29 print("Florida's abbreviation is: ", states['Florida']) +30 +31 # do it by using the state then cities dict +32 print('-' * 10) +33 print("Michigan has: ", cities[states['Michigan']]) +34 print("Florida has: ", cities[states['Florida']]) +35 +36 # print every state abbreviation +37 print('-' * 10) +38 for state, abbrev in list(states.items()): +39 print(f"{state} is abbreviated {abbrev}") +40 +41 # print every city in state +42 print('-' * 10) +43 for abbrev, city in list(cities.items()): +44 print(f"{abbrev} has the city {city}") +45 +46 # now do both at the same time +47 print('-' * 10) +48 for state, abbrev in list(states.items()): +49 print(f"{state} state is abbreviated {abbrev}") +50 print(f"and has city {cities[abbrev]}") +51 +52 print('-' * 10) +53 # safely get a abbreviation by state that might not be there +54 state = states.get('Texas') +55 +56 if not state: +57 print("Sorry, no Texas.") +58 +59 # get a city with a default value +60 city = cities.get('TX', 'Does Not Exist') +61 print(f"The city for the state 'TX' is: {city}") +``` +一个小练习,尝试自己写一个中国省份与省份缩写对应的字典代码 +## (6)元组 +元组是另一个数据类型,类似于 List(列表)。 + +元组用 () 标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。 + +```python +tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 ) +tinytuple = (123, 'john') + +print(tuple) # 输出完整元组 +print(tuple[0]) # 输出元组的第一个元素 +print(tuple[1:3]) # 输出第二个至第四个(不包含)的元素 +print(tuple[2:]) # 输出从第三个开始至列表末尾的所有元素 +print(tinytuple * 2) # 输出元组两次 +print(tuple + tinytuple) # 打印组合的元组 +``` + +以下是元组无效的,因为元组是不允许更新的。而列表是允许更新的: + +```python +tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 ) +list = [ 'runoob', 786 , 2.23, 'john', 70.2 ] +tuple[2] = 1000 # 元组中是非法应用 +list[2] = 1000 # 列表中是合法应用 +``` + +## (7)布尔类型 +这个部分相信大家已经很熟悉,在高中和大学数学中经常出现的 +在python表述的语法是 + +• and +• or +• not +• != (不等于) +• == (等于) +• >= (大于等于) +• <= (小于等于) +• True +• False + + +在这个练习中,你将试着在 Python 中运用逻辑表。给以下每一个逻辑问题写下你认为的答案,要么是 True,要么是 False。等你把答案写下来,再在终端里运行 Python,输入每个逻辑问题,来确认你的答案是否正确。 + +```python +1. True and True +2. False and True +3. 1 == 1 and 2 == 1 +4. "test" == "test" +5. 1 == 1 or 2 != 1 +6. True and 1 == 1 +7. False and 0 != 0 +8. True or 1 == 1 +9. "test" == "testing" +10. 1 != 0 and 2 == 1 +11. "test" != "testing" +12. "test" == 1 +13. not (True and False) +14. not (1 == 1 and 0 != 1) +15. not (10 == 1 or 1000 == 1000) +16. not (1 != 10 or 3 == 4) +17. not ("testing" == "testing" and "Zed" == "Cool Guy") +18. 1 == 1 and (not ("testing" == 1 or 1 == 0)) +19. "chunky" == "bacon" and (not (3 == 4 or 3 == 3)) +20. 3 == 3 and (not ("testing" == "testing" or "Python" == "Fun")) +``` + +##### 你将会看到 + +在你尝试给出所有答案后,这是你可能会在 Python 运行后看到的会话结果: + +```python +Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12) +[GCC 4.0.1 ( Apple Inc . build 5465)] on darwin +Type "help" , "copyright" , "credits" or "license" for more information +>>> True and True +True +>>> 1 == 1 and 2 == 2 +True +``` + + + +## (8)读写文件 + +- **close** - 关闭文件,就像编辑器中的 “文件->另存为”一样。 +- **read** - 读取文件内容。你可以把读取结果赋给一个变量。 +- **readline** - 只读取文本文件的一行内容。 +- **truncate** - 清空文件。清空的时候要当心。 +- **write('stuff')** - 给文件写入一些“东西”。 +- **seek(0)** - 把读/写的位置移到文件最开头。 + +这些都是你需要知道的一些非常重要的命令。其中一些要用到参数,但是我们暂且不去重点关注。你只需要记住 `write` 命令需要你提供一个你要写入的文件的字符串参数。 + +让我们用这些命令做一个小小的编辑器: + +```python +1 from sys import argv +2 +3 script, filename = argv +4 +5 print(f"We're going to erase {filename}.") +6 print("If you don't want that, hit CTRL-C (^C).") +7 print("If you do want that, hit RETURN.") +8 +9 input("?") +10 +11 print("Opening the file...") +12 target = open(filename, 'w') +13 +14 print("Truncating the file. Goodbye!") +15 target.truncate() +16 +17 print("Now I'm going to ask you for three lines.") +18 +19 line1 = input("line 1: ") +20 line2 = input("line 2: ") +21 line3 = input("line 3: ") +22 +23 print("I'm going to write these to the file.") +24 +25 target.write(line1) +26 target.write("\n") +27 target.write(line2) +28 target.write("\n") +29 target.write(line3) +30 target.write("\n") +31 +32 print("And finally, we close it.") +33 target.close() +``` + +这真是一个很大的文件,可能是你输入过的最大的文件了。所以慢一点,写完检查一下,然后再运行。你也可以写一点运行一点,比如先运行 1-8 行,然后再多运行 5 行,然后再多几行,直到所有的都完成和运行了。 + +#### 你应该看到 + +事实上你应该看到两样东西,首先是你新脚本的输出结果: + +```pyhton +$ python3.6 ex16.py test.txt We're going to erase test.txt. +If you don't want that, hit CTRL-C (^C). If you do want that, hit RETURN. +? +Opening the file... +Truncating the file. Goodbye! +Now I'm going to ask you for three lines. +line 1: Mary had a little lamb +line 2: Its fleece was white as snow +line 3: It was also tasty +I'm going to write these to the file. +And finally, we close it. +``` + +现在,用编辑器打开你创建的文件(比如我的是 test.txt),检查一下是不是对的。 + +### 附加练习 + +1. 如果你理解不了这个练习,回过头去按照给每行加注释的方法再过一遍,注释能帮助你理解每一行的意思,至少让你知道你不理解的地方在哪里,然后动手去查找答案。 +2. 写一个类似于上个练习的脚本,使用 `read` 和 `argv` 来读取你刚刚创建的文件。 +3. 这个练习中有太多的重复,试着用一个 `target.write()` 命令来打印 line1、line2、line3,你可以使用字符串、格式字符串和转义字符。 +4. 弄明白为什么我们要用一个 `'w'` 作为一个额外的参数来打开。提示:通过明确说明你想要写入一个文件,来安全地打开它。 +5. 如果你用 `w` 模式打开文件,那你还需要 `target.truncate()` 吗? 读一读 Python 的 open 函数文件,来搞明白这个问题。 + +### 常见问题 + +**`truncate()` 对于 `'w'` 参数来说是必须的吗?** 详见附加练习 5。 + +**`'w'` 到底是什么意思?** 它真的只是一个有字符的字符串,来表示文件的一种模式。如果你用了 `'w'` ,就代表你说“用 ‘write’ 模式打开这个文件。此外还有 `'r'` 表示 read 模式,`'a'` 表示增补模式,后面还可能加一些修饰符(modifiers)。 + +**我能对文件使用哪些修饰符?** 目前最重要的一个就是 `+` ,你可以用 `'w+'`, `'r+'` 以及 `'a+'`。这样会让文件以读和写的模式打开,取决于你用的是那个符号以及文件所在的位置等。 + +**如果只输入 `open(filename)` 是不是就用 `'r'` (读)模式打开?** 是的,那是 `open()` 函数的默认值。 + +### 读写文件方法与经验总结 + +``` +my_text = "今天又是一周的开始,打起精神认真赚钱不含参" + +with open("path", "w", encoding="utf-8") as f: + f.write(my_text) +``` + +​ 写入数据的时候最好是指定一下文件的编码方式,不然下次读取的时候可能就读取不了了(出现乱码)。经常遇到的问题是中文的保存,会以各种各样的编码方式保存。但其实在读取的时候选择对应的编码方式仍旧可以打开但直接保存为utf-8一劳永逸。特别是使用pandas将含有中文数据的DataFrame对象保存为csv文件的时候,有一个具体的编码方式需要指定。 + +​ 其次如果是爬取的图片类型的数据此时的写入方式就需要更改为二进制方式保存,也是之前困扰过的问题。 + +​ 如果爬取的文本中含有emoji而且准备写入mysql中,需要更改mysql数据库的编码方式为utf-8mb4格式,不然会出现问题。mysql数据库的版本也有要求具体5.10以上应该都可以~ + +​ 数据的存写最好是使用with open() as f这种形式,上下文管理器会自动帮你读取完数据后关闭文件。不然在报错后寻找问题的原因真的很麻烦,一个小问题可能要找很久也找不到(亲生经历)。 + +​ 如果遇到一个不确定是什么编码方式的文档,最好的方式是以txt打开该文件可以看到文件的编码方式,此时也可以另存为的时候将编码方式改为自己需要的合适的编码方式。 + +​ 大文件的读写,很浪费时间而且对于内存的负担也很大。此时可以对数据进行分页读取比较合适 内存毕竟有限。pickle,和json可以将数据存储为二进制文件和通用的json格式文件。可能需要注意的地方就是dump和dunps以及load和loads的区别。这个真的是一直没注意每次都随机试,反正只最多需要试两下就可以,多试几次就知道了。pickle保存的.pkl文件内存小,读取快。真的非常和,json文件的引号需要注意一下。还有就是json文件load的时候如果数据有问题就直接写正则对数据做拆分,避免所有数据都被丢失。之前遇到过json文件保存明明可以,但是读取就是失败的问题。后来发现是有一些字符编码有问题,会具体报错的那个位置,可以自行定位一点一点的排除。网上有一个解决思路是有一个参数,控制解码相关的设置一下就可以了,但并不是万能的至少没解决我之前遇到的问题。 + +数据的写入读取方式:只读,只写,覆盖写等这些容易忽略很容易将幸幸苦苦的数据保存出问题然后发现结果不对劲。回头一看才发现是数据的写入有问题,这样就很消磨热情以及浪费时间。 + +#### 解决问题的思路: + +​ 我不是计算机专业的,周围认识的人也没有学编程的。因此每当我遇到问题的时候就借助baidu,csdn,博客园这些。现在最主要还是谷歌要用的多,百度最差其次csdn总是跳来跳去也找不到答案,博客园如果有答案的话内容感觉还可以csdn挑来挑去没找到解决办法很烦人不过也好用。谷歌报错代码挺方便的,容易检索出来比较相似的问题。 + +更多的时候自己多试几下就能发现问题的原因,记得也更清楚一些。而且每当一个困扰很久的问题解决后的那种成就感真的很爽,有一种如释负重的感觉。 + + + + + + diff --git a/PythonThinking/task4-函数.md b/PythonThinking/task4-函数.md new file mode 100644 index 0000000..621a6db --- /dev/null +++ b/PythonThinking/task4-函数.md @@ -0,0 +1,364 @@ +## (9)函数 + +这是一个很大的标题。接下来我要给你介绍一下函数。每一个程序员都要一遍一遍地用到函数,思考它们的作用以及如何使用它们,但是我会给你一些最简单的解释,让你能够快速上手。 + +函数一般就是做以下这些事情: + +1. 它们为一些代码起名字,就像变量为字符串和数字起名字一样。 +2. 它们像脚本获取 `argv` 一样获取参数(arguments)。 +3. 通过 1 和 2 的操作,让你做一些你自己的“小脚本”或者“微命令”。 + +你可以通过在 Python 中使用 `def` 来创建一个函数。我会让你创建 4 个不同的函数,它们就像你的脚本一样运行,之后我还会想你展示每一个之间是如何关联的。 + +```python +1 # this one is like your scripts with argv +2 def print_two(*args): +3 arg1, arg2 = args +4 print(f"arg1: {arg1}, arg2: {arg2}") +5 +6 # ok, that *args is actually pointless, we can just do this +7 def print_two_again(arg1, arg2): +8 print(f"arg1: {arg1}, arg2: {arg2}") +9 +10 # this just takes one argument +11 def print_one(arg1): +12 print(f"arg1: {arg1}") +13 +14 # this one takes no arguments +15 def print_none(): +16 print("I got nothin'.") +17 +18 +19 print_two("Zed","Shaw") +20 print_two_again("Zed","Shaw") +21 print_one("First!") +22 print_none() +``` + +让我们把第一个函数拆解一下,`print_two` 这是你从创建脚本中已经学到的最熟悉的东西: + +1. 首先,我们告诉 Python 我们想要用 `def` (即 define)来创建一个函数。 +2. 在 `def` 的同一行我们给了函数一个名字,本例中是 `print_two`,但是你也可以起名叫“peanuts”(花生),名字没关系,不过最好简短一些,并且能够说明这个函数的作用。 +3. 然后我们告诉它我们想要 `*args` ,它很像参数 `args` ,只不过是为函数设的,必须放在括号里面才能工作。 +4. 然后我们以 `:` 结束这一行,另起一行开始缩进。 +5. 在 `:` 之后缩进四个空格的所有行都是关于 `print_two` 这个函数名的。我们第一个缩进的行就是用来解包这个参数(argument),跟之前的脚本一样。 +6. 要表明它是如何工作的,我们把这些参数打印了出来,就像我们在脚本中所做的一样。 + +`print_two` 的问题是它不是创建一个函数最简单的方法。在 python 里面,我们可以跳过整个解包参数的过程,只用我们需要的 `()` 里面的名字即可,这也正是 `print_two_again` 所做的事情。 + +之后我们用一个参数创建了 `print_one` 这个函数。 + +最后我们创建了一个没有参数的函数 `print_none`。 + +| 警告! | +| :----------------------------------------------------------- | +| 这很重要。如果你现在不太明白,别急着灰心,我们会再做几个跟函数相关的练习来进一步学习。现在当我说“函数”的时候,你就把它想象成一个“迷你脚本”,跟着做就行了。 | + +#### 你会看到 + +如果你运行了,你会看到: + +``` +arg1: Zed, arg2: Shaw +arg1: Zed, arg2: Shaw +arg1: First! +I got nothin'. +``` + +现在你已经看到了函数是如何工作的。注意你使用函数的方式就像你使用 exists、open 等其他一些“命令”一样。其实我一直在跟你卖关子,因为在 python 里面,这些“命令”就是“函数”。这意味着你可以创建你自己的命令然后在你的脚本中使用。 + +#### 附加练习 + +创建一个如下的函数 checklist (核查表)用于后面的练习。把这些内容写在索引卡上,一直保留到你完成所有剩余练习的时候或者当你感觉你不再需要这些索引卡的时候: + +1. 你是否用 `def` 来创建函数了? +2. 你的函数名是只包含字符和 `_` (下划线)吗? +3. 你在函数名后面放 `(` (左圆括号)了吗? +4. 你在左圆括号后面放参数(argument)了吗?参数之间是以逗号隔开的吗?) +5. 你的每个参数都是唯一的吗(即没有重名)? +6. 你在参数后面放 `)` (右圆括号)和 `:` (冒号)了吗? +7. 你在与这个函数相关的代码行前面加上四个空格的缩进了吗?(不能多,也不能少) +8. 你是通过另起一行不缩进来结束你的函数的吗? + +当你运行(使用或者调用)一个函数时,检查以下事项: + +1. 你是通过输入函数名称来运行/调用/使用一个函数的吗? +2. 你运行的时候有在名称后面加 `(` 吗? +3. 你有把你想要的值放在圆括号里并用逗号隔开了吗? +4. 你是以 `)` 来结束调用这个函数的吗? + +在接下来的课程中用这两个 checklist ,直到你不再需要它们为止。 + +最后,再强调以下,我说的“运行”(run)、“调用”(call)、“使用”(use)都是一个意思。 + +#### 常见问题 + +**函数名称有哪些要求?**跟变量名一样,任何不以数字开头的字母、数字、下划线组合都可以。 + +**`\*args` 中的 `\*` 是什么作用?**这是告诉 Python 取所有的参数给函数,然后把它们放在 `args` 里放成一列,很像你之前学的 `argv` ,只不过这个是为函数设置的。这种不常用,除非有特殊需要。 + +**这部分好无聊好烦人啊。**这就对了,这说明你已经开始一边输入代码一边思考它的作用了。如果想让它不这么无聊,按照我的要求一字不差地输入进去,然后再故意打乱它们,看看你能不能修复好。 + +### 函数和变量 + +函数是一个信息量巨大的东西,但是别担心,老老实实做练习,仔仔细细核对 checklist,你最终会掌握它的。 + +有个小点你可能没注意到,我们会在之后进行强化:你函数里面的变量跟你脚本里面的变量没有关联。通过下面这个练习思考一下这个问题: + +```python +1 def cheese_and_crackers(cheese_count, boxes_of_crackers): +2 print(f"You have {cheese_count} cheeses!") +3 print(f"You have {boxes_of_crackers} boxes of crackers!" +4 print("Man that's enough for a party!") +5 print("Get a blanket.\n") +6 +7 +8 print("We can just give the function numbers directly:") +9 cheese_and_crackers(20, 30) +10 +11 +12 print("OR, we can use variables from our script:") +13 amount_of_cheese = 10 +14 amount_of_crackers = 50 +15 +16 cheese_and_crackers(amount_of_cheese, amount_of_crackers) +17 +18 +19 print("We can even do math inside too:") +20 cheese_and_crackers(10 + 20, 5 + 6) +21 +22 +23 print("And we can combine the two, variables and math:") +24 cheese_and_crackers(amount_of_cheese + 100, amount_of_crackers + 1000) +``` + +这个练习展示了我们可以给函数 `cheese_and_crackers` 赋值的几种不同的方式,我们可以直接给它数字,或者变量,亦或是数学运算,甚至是数学运算和变量的结合。 + +从某种程度上说,函数的参数有点类似于我们给变量赋值时的 `=` 符号 。事实上,如果你可以用 `=` 来定义一个东西,你就可以把它作为参数赋给函数。 + +#### 你会看到 + +你应该研究一下这个脚本的输出结果,把它和你之前的脚本输出结果对比一下。 + +```python +We can just give the function numbers directly: +You have 20 cheeses! +You have 30 boxes of crackers! +Man that's enough for a party! +Get a blanket. + +OR, we can use variables from our script: +You have 10 cheeses! +You have 50 boxes of crackers! +Man that's enough for a party! +Get a blanket. + +We can even do math inside too: +You have 30 cheeses! +You have 11 boxes of crackers! +Man that's enough for a party! +Get a blanket. + +And we can combine the two, variables and math: +You have 110 cheeses! +You have 1050 boxes of crackers! +Man that's enough for a party! +Get a blanket. +``` + +#### 附加练习 + +1. 回顾一遍这个脚本,然后在每一行上方加上注释,解释它的作用。 +2. 从下到上阅读每一行,说出所有重要的字符。 +3. 写至少一个自己设计的函数,然后用 10 种不同的方式运行它。 + +#### 常见问题 + +**运行一个函数怎么可能有 10 种不同的方式?** 爱信不信,理论上讲,任何函数都有无数种调用方式。看看你对于函数、变量以及用户输入的创造力有多强。 + +**有没有什么方法能分析函数是如何运行的,以帮助我更好地理解它?**有很多方法,但是你先试试给每行加注释这种方式。其他方法包括大声把代码读出来,或者把代码打印出来然后在上面画图,来展示它是怎么运行的。 + +**如果我想问用户关于 cheese 和 crackers 的数字呢?**你需要用 `int()` 来把你通过 `input()` 获取的内容转化成数值。 + +**在函数中创建 `amount_of_cheese` 这个变量会改变 `cheese_count` 这个变量吗?** 不会的,这些变量是相互独立并存在于函数之外的。它们之后会传递给函数,而且是“暂时版”,只是为了让函数运行。当函数退出之后,这些暂时的变量就会消失,其他一切正常运行。接着往下学,你会慢慢明白的。 + +**像 `amount_of_cheese` 这样的全局变量(`global variables`)跟函数变量同名的话是不是不太好?**是的,如果这样的话,你就不知道你说的到底是哪个变量了。不过你有时候可能不得不用同样的名字,或者你可能不小心同名了,不管怎么样,尽量避免这种情况。 + +**一个函数里包含的参数有数量限制吗?**这取决于 Python 的版本以及你的电脑,但是这个数量其实相当大。实践中一个函数包含 5 个参数为宜,再多就比较难用了。 + +**你能在一个函数里面调用一个函数吗?**可以,在之后的练习里你会创建一个小游戏,到时候就会用到这个。 + +### 函数和文件 + +记住你的函数 checklist,然后在做这个练习的时候注意函数是如何和文件一起工作并发挥一些作用的。 + +ex20.py + +```python +1 from sys import argv +2 +3 script, input_file = argv +4 +5 def print_all(f): +6 print(f.read()) +7 +8 def rewind(f): +9 f.seek(0) +10 +11 def print_a_line(line_count, f): +12 print(line_count, f.readline()) +13 +14 current_file = open(input_file) +15 +16 print("First let's print the whole file:\n") +17 +18 print_all(current_file) +19 +20 print("Now let's rewind, kind of like a tape.") +21 +22 rewind(current_file) +23 +24 print("Let's print three lines:") +25 +26 current_line = 1 +27 print_a_line(current_line, current_file) +28 +29 current_line = current_line + 1 +30 print_a_line(current_line, current_file) +31 +32 current_line = current_line + 1 +33 print_a_line(current_line, current_file) +``` + +着重注意我们是如何在每次运行 print_a_line 的时候把当前行的数字传递出去的。 + +#### 你会看到 + +```python +$ python3.6 ex20.py test.txt +First let's print the whole file: + +This is line 1 +This is line 2 +This is line 3 + +Now let's rewind, kind of like a tape. +Let's print three lines: +1 This is line 1 + +2 This is line 2 + +3 This is line 3 +``` + +#### 附加练习 + +1. 在每一行上方添加注释解释它的作用。 +2. 每次 `print_a_line` 运行的时候,你都在传入一个 `current_line` 变量。写出每一次调用函数的时候 `current_line` 等于什么,然后找出它是如何变成`print_a_line` 里面的 `line_count` 的。 +3. 找出每一个用到函数的地方,然后检查它的 `def` 确保你给出了正确的参数。 +4. 在网上搜搜 `seek` 这个函数的作用。试着输入 `pydoc file`,看看你能否从这里看明白。然后试着输入 `pydoc file.seek` 再看看 `seek` 是用来干嘛的。 +5. 搜一下简化符号 `+=` ,然后用 `+=` 重新写这个脚本。 + +#### 常见问题 + +**在 `print_all` 和其他函数里的 `f` 是什么东西?** `f` 是一个变量,就像你在练习 18 中函数的变量一样,只不过这次它是一个文件。文件在 Python 里面有点类似于一个老式电脑里面的磁带驱动器,或者一个 DVD 播放机。它有一个“读取头”(read head),你可以在文件里 `seek` (寻找)这个读取头所在的位置,然后在那里工作。每次你做 `f.seek(0)` 的时候你都会从移动到文件最开始,每次你做 `f.readline()` 的时候,你都在从文件里读取一行内容,并且把读取头移动到 `\n` 后面,也就是每行结束的地方。 我会在后面给你做更详细的解释。 + +**为什么 `seek(0)` 没有把 `current_line` 设置为 0?** 首先,`seek()` 函数处理的是字节(bytes),不是行。`seek(0)` 这个代码把文件移动到 0 字节(也就是第一个字节处)。其次,`current_line` 只是一个变量并且跟这个文件没有任何实际联系。我们是在手动累加它。 + +**什么是 `+=` ?** 你知道在英语里我们可以把 “it is” 写成 “it's” ,或者把 “you are” 写成“you're” ,这叫缩写(contraction)。而 `+=` 就像 `=` 和 `+` 两种运算的缩写。也就是 `x = x + y` 就等同于 `x += y` 。 + +**`readline()` 是怎么知道每一行在哪儿的?** `readline()` 里面的代码能够扫描文件的每个字节,当它发现一个 `\n` 字符,它就会停止扫描这个文件,然后回到它发现的地方。文件 `f` 就负责在每次调用 `readline()` 之后维持文件的当前位置,以此来保证它能阅读到每一行。 + +**为什么文件中的行之间会有空行?** `readline()` 函数返回文件中每行最后的 `\n` 。又在 `print` 函数的结尾加上一个 `end = " "` 来避免给每行加上两个 `\n` 。 + +### 函数可以返回一些东西 + +你已经使用了 `=` 来命名变量并给变量赋予数值或字符串。接下来我会教你如何用 `=` 和一个新的 python 字符 `return` 来把函数中的变量设置为一个值。有一点需要密切注意,但是先输入如下代码: + +```python +1 def add(a, b): +2 print(f"ADDING {a} + {b}") +3 return a + b +4 +5 def subtract(a, b): +6 print(f"SUBTRACTING {a} - {b}") +7 return a - b +8 +9 def multiply(a, b): +10 print(f"MULTIPLYING {a} * {b}") +11 return a * b +12 +13 def divide(a, b): +14 print(f"DIVIDING {a} / {b}") +15 return a / b +16 +17 +18 print("Let's do some math with just functions!") +19 +20 age = add(30, 5) +21 height = subtract(78, 4) +22 weight = multiply(90, 2) +23 iq = divide(100, 2) +24 +25 print(f"Age: {age}, Height: {height}, Weight: {weight}, IQ: {iq}") +26 +27 +28 # A puzzle for the extra credit, type it in anyway. +29 print("Here is a puzzle.") +30 +31 what = add(age, subtract(height, multiply(weight, divide(iq, 2)))) +32 +33 print("That becomes: ", what, "Can you do it by hand?") +``` + +我们现在要做我们自己的加减乘除数学运算了。我说的要密切注意的是 `add` 函数里面的 `return a + b` ,这步做的是这些事情: + +1. 我们的函数是以两个参数被调用的: `a` 和 `b` 。 +2. 我们把函数所做的事情打印出来,在本例中是 “ADDING”。 +3. 然后我们让 Python 做一些反向的事情:我们返回 `a + b` 的和。你可以这样描述:我用 `a` 加上 `b` ,然后返回它们的结果。 +4. Python 把这两个数加起来。然后当函数终止的时候,运行了这个函数的任何一行都能够将 `a + b` 的结果赋予一个变量。 + +和这本书里其他内容比起来,这块你确实应该把节奏放慢一些,把代码打乱,然后试着琢磨一下每一步都发生了什么。 + +#### 你会看到 + +```python +Let's do some math with just functions! +ADDING 30 + 5 +SUBTRACTING 78 - 4 +MULTIPLYING 90 * 2 +DIVIDING 100 / 2 +Age: 35, Height: 74, Weight: 180, IQ: 50.0 +Here is a puzzle. +DIVIDING 50.0 / 2 +MULTIPLYING 180 * 25.0 +SUBTRACTING 74 - 4500.0 +ADDING 35 + -4426.0 +That becomes: -4391.0 +Can you do it by hand? +``` + +#### 附加练习 + +1. 如果你还不能真正理解 `return` 是干什么的,试着写几个你自己的函数,并且让它们返回一些值。你可以让它 `return` 任何东西,只要你把它们放在 `=` 右边即可。 +2. 脚本的最后是一个难题。我在用一个函数的返回值作为另一个函数的参数,这是在一个链(chain)里面进行的,这样就用函数创建了一个公式。它看起来确实很难,但是如果你运行这个脚本,你就可以看到结果。你要做的就是试着弄明白创建同样操作的平常的函数是什么样的。 +3. 一旦你有了可以解出这个难题的公式,试着对函数的某些部分做做改动,看看会发生什么。有意改动一些数让它产生一些不同的值。 +4. 做相反的操作。写一个简单的公式,然后用同一种方式通过函数来计算它。 + +这个练习可能真的很让你头大,但是放松,慢点学,把它当成是一个小游戏。正是解决这样的难题让编程如此有趣,所以之后我还会再给你一些小问题让你解决。 + +#### 常见问题 + +**为什么 python 是“从后往前”(backward打印公式或者函数的?** 它其实不是从后往前,它是从里到外(inside out)。当你开始把代码打乱成分开的公式和函数时,你会看到它是如何工作的。试着理解我说的 “inside out” 而不是 “backward” 。 + +**我如何使用 `input()` 来输入我自己的值?**还记得 `int(input())` 吗?这样做的问题是你不能输入浮点数,所以试着用 `float(input())` 来代替。 + +**你说的“写一个公式”是什么意思?** 先试试 `24 + 34 / 100 - 1023` 吧,变成使用函数来计算。然后自己想出一个类似的数学公式,要用变量让它看起来更像一个公式。 + + + + + + + + diff --git a/PythonThinking/task5-编程习惯养成与思维.md b/PythonThinking/task5-编程习惯养成与思维.md new file mode 100644 index 0000000..3db3eea --- /dev/null +++ b/PythonThinking/task5-编程习惯养成与思维.md @@ -0,0 +1,90 @@ +# 3、编程习惯养成与思维 + + + +## (1)防御性编程与备注 +防御性编程的基本思想 +假设A,如果您从用户那里获得输入他们不一定会提供您所要求的输入,因此如果您要求的是正数,请不要指望他们给你一个 +然后是假设B,如果您正在使用一个由不完美的程序员编写的程序,也许是我,或者您自己,那个程序中可能有错误,所以您编写程序的假设是不仅用户可能会犯错,程序的其他部分也可能会犯错,并且您只是在假设您宁愿发现某些事情出错,然后让它出错的假设下进行了许多不同的测试,不知道问题的来源 +但记住的主要事情是:人们是愚蠢的一般原则,并会犯错 +因此您编写程序的目的是避免在犯这些错误时发生灾难 +要养成编写防御性编码的习惯 + +#### 防御性编程样例: +假设我想找到某个整数的所有除数,我想弄清楚所有的除数是什么,选择了在循环中间打印出来。 +```python +x = 10 +i = 1 +while i cats: +10 print("Not many cats! The world is saved!") +11 +12 if people < dogs: +13 print("The world is drooled on!") +14 +15 if people > dogs: +16 print("The world is dry!") +17 +18 +19 dogs += 5 +20 +21 if people >= dogs: +22 print("People are greater than or equal to dogs.") +23 +24 if people <= dogs: +25 print("People are less than or equal to dogs.") +26 +27 +28 if people == dogs: +29 print("People are dogs.") +``` +运行结果 + +```python +Too many cats! The world is doomed! +The world is dry! +People are greater than or equal to dogs. +People are less than or equal to dogs. +People are dogs. +``` +#### 附加练习 +在附加练习中,试着猜猜 if 语句是什么以及它是干什么的。在继续进行下个练习之前,试着用自己的话回答以下这些问题, + +1、你认为 if 对它下面的代码起什么作用? +2、为什么 if 下面的代码要缩进 4 个空格? +3、如果没有缩进会发生什么? +4、你能把一些布尔表达式放进 if 语句吗?试试看。 +5、如果你改变 people,cats 和 dogs 的初始值会发生什么? +#### 常见问题 ++= 是什么意思? x += 1 就相当于 x = x + 1 ,但是输入的内容更少。你可以把它叫做“累加”(increment by)运算符。之后你还会学到 -= 这样类似的表达。 +#### Else 和 if +在上个练习中你学到了一些 if 语句,思考了它的含义和作用。在你学习更多内容之前,我会解释一下上个附加练习中的问题。首先确定你做了那些练习。 + +1. 你认为 if 对它下面的代码起什么作用? + +if 语句在代码中创建了一个“分支”(branch),有点类似于在一本冒险书中,你选择了哪个答案,就翻到对应的一页,如果你选择了不同的答案,就会去到不同的地方。if 语句就是告诉脚本,如果这个布尔表达式是 True,那就运行它下面的代码,否则的话就跳过。 + +2. 为什么 if 下面的代码要缩进 4 个空格? + +通过一行代码结尾的冒号告诉 Python 你在创建一个新的代码块,然后缩进四个空格告诉 Python 这个代码块中都有些什么。这就跟本书前半部分中你学的函数是一样的。 + +3. 如果没有缩进会发生什么? + +如果没有缩进,你很可能收到一个错误提示。Python 一般会让你在一个带 : 的代码行下面缩进一些内容。 + +4. 你能把一些布尔表达式放进 if 语句吗?试试看。 + +试试吧,你可以的。你可以把它们写得很复杂,不过复杂的东西一般风格都很糟糕。 + +5. 如果你改变 people,cats 和 dogs 的初始值会发生什么? + +因为你在比较数字,所以如果你改变了数字,不同的 if 语句将会得出不同的判断结果,那么下面某些代码块就有可能运行。回到练习中给这些变量一些不同的数值,然后看看你能否在脑中判断出来哪些代码块会运行。 + +把我的答案和你的比较一下,然后确保你真的理解了代码块的概念。这对你进行接下来的练习很重要。把下面的代码输入进去然后运行。 + +```python +1 people = 30 +2 cars = 40 +3 trucks = 15 +4 +5 +6 if cars > people: +7 print("We should take the cars.") +8 elif cars < people: +9 print("We should not take the cars.") +10 else: +11 print("We can't decide.") +12 +13 if trucks > cars: +14 print("That's too many trucks.") +15 elif trucks < cars: +16 print("Maybe we could take the trucks.") +17 else: +18 print("We still can't decide.") +19 +20 if people > trucks: +21 print("Alright, let's just take the trucks.") +22 else: +23 print("Fine, let's stay home then.") +``` + +运行结果 + +```python +We should take the cars. +Maybe we could take the trucks. +Alright, let's just take the trucks. +``` +##### 附加练习 +1、试着猜猜 elif 和 else 的作用是什么。 +2、改变 cars,people,和 trucks 的数值,然后追溯每一个 if 语句,看看什么会被打印出来。 +3、试试一些更复杂的布尔表达式,比如cars > people 或者 trucks < cars。 +4、在每一行上面加上注释。 + +##### 常见问题 +如果多个 elif 块都是 True 会发生什么? Python 从顶部开始,然后运行第一个是 True 的代码块,也就是说,它只会运行第一个。 + + +#### IF嵌套使用 +前面主要学习了调用函数、打印东西,但是这些基本都是直线运行下来的。你的脚本从上面开始运行,然后到底部结束。如果你用了一个函数,你可以随后再运行它,但是仍然不会有分叉需要你做决定的情况。现在你学习了 if,else,以及 elif,你就可以让脚本来做决定了。 + +在上个脚本中你写出了一个简单的问问题的测试集。在这个练习中你将问用户一些问题,并基于他们的回答做决定。写下这个脚本,然后多玩几遍,把它弄明白。 + +```python +1 print("""You enter a dark room with two doors. +2 Do you go through door #1 or door #2?""") +3 +4 door = input("> ") +5 +6 if door == "1": +7 print("There's a giant bear here eating a cheese cake.") +8 print("What do you do?") +9 print("1. Take the cake.") +10 print("2. Scream at the bear.") +11 +12 bear = input("> ") +13 +14 if bear == "1": +15 print("The bear eats your face off. Good job!") +16 elif bear == "2": +17 print("The bear eats your legs off. Good job!") +18 else: +19 print(f"Well, doing {bear} is probably better.") +20 print("Bear runs away.") +21 +22 elif door == "2": +23 print("You stare into the endless abyss at Cthulhu's retina.") +24 print("1. Blueberries.") +25 print("2. Yellow jacket clothespins.") +26 print("3. Understanding revolvers yelling melodies.") +27 +28 insanity = input("> ") +29 +30 if insanity == "1" or insanity == "2": +31 print("Your body survives powered by a mind of jello.") +32 print("Good job!") +33 else: +34 print("The insanity rots your eyes into a pool of muck.") +35 print("Good job!") +36 +37 else: +38 print("You stumble around and fall on a knife and die. Good job!") +``` +这里很关键的一点是你现在在 if 语句里面又放了一个 if 语句。这在创建“嵌套”(nested)决定的时候非常有用,每一个分支指向另一个选择。 + +确保你理解了在 if 语句中嵌套 if 语句的理念。你可以通过做附加练习来真正掌握它。 +##### 你会看到 +这是我玩这个冒险小游戏的结果,我可能玩得没那么好。 + +```python +You enter a dark room with two doors. +Do you go through door #1 or door #2? +> 1 +There's a giant bear here eating a cheese cake. +What do you do? +1. Take the cake. +2. Scream at the bear. +> 2 +The bear eats your legs off. Good job! +``` +##### 附加练习 +给这个游戏加一些新内容,同时改变用户可以做的决定。尽可能地扩展这个游戏,直到它变得很搞笑。 +写一个完全不同的新游戏。可能你不喜欢我的这个,你可以做一个你自己的。 + +##### 常见问题 +我能用一系列的 if 语句来代替 elif 吗?在某些情况下可以,但是取决于每个 if/else 是怎么写的。如果这样的话还意味着 Python 将会检查每一个 if-else 组合,而不是像 if-elif-else 组合那样只会检查第一个是 false 的。你可以多试几次,感受一下区别。 + +我如何表示一个数字的区间?有两种方式:一种是 0 < x < 10 或者 1 <= x < 10 这种传统表示方法,另一种是 x 的区间是 (1, 10)。 + +如果我想在 if-elif-else 代码块中放更多的选择怎么办?为每种可能的选择增加更多的 elif 块。 +### FOR语句 + +```python +1 the_count = [1, 2, 3, 4, 5] +2 fruits = ['apples', 'oranges', 'pears', 'apricots'] +3 change = [1, 'pennies', 2, 'dimes', 3, 'quarters'] +4 +5 # this first kind of for-loop goes through a list +6 for number in the_count: +7 print(f"This is count {number}") +8 +9 # same as above +10 for fruit in fruits: +11 print(f"A fruit of type: {fruit}") +12 +13 # also we can go through mixed lists too +14 # notice we have to use {} since we don't know what's in it +15 for i in change: +16 print(f"I got {i}") +17 +18 # we can also build lists, first start with an empty one +19 elements = [] +20 +21 # then use the range function to do 0 to 5 counts +22 for i in range(0, 6): +23 print(f"Adding {i} to the list.") +24 # append is a function that lists understand +25 elements.append(i) +26 +27 # now we can print them out too +28 for i in elements: +29 print(f"Element was: {i}") +``` +##### 运行结果 + +```python +This is count 1 +This is count 2 +This is count 3 +This is count 4 +This is count 5 +A fruit of type: apples +A fruit of type: oranges +A fruit of type: pears +A fruit of type: apricots +I got 1 +I got pennies +I got 2 +I got dimes +I got 3 +I got quarters +Adding 0 to the list. +Adding 1 to the list. +Adding 2 to the list. +Adding 3 to the list. +Adding 4 to the list. +Adding 5 to the list. +Element was: 0 +Element was: 1 +Element was: 2 +Element was: 3 +Element was: 4 +Element was: 5 +``` +##### 附加练习 +看看你是如何使用 range 的。查阅上面的 range 函数并理解掌握。 +你能在第 22 行不使用 for-loop,而是直接把 range(0, 6) 赋给 elements 吗? +找到 Python 文档关于列表的部分,然后读一读。看看除了 append,你还能对列表做哪些操作? +##### 常见问题 +如何创建一个二维列表?可以用这种列表中的列表:[[1,2,3],[4,5,6]] + +列表(lists)和数组(arrays)难道不是一个东西吗?这取决于语言以及实现方法。在传统术语中,列表和数组的实现方式不同。在 Ruby 中都叫做 arrays,在 python 中都叫做 lists。所以我们就把这些叫做列表吧。 + +为什么 for-loop 可以用一个没有被定义的变量?变量在 for-loop 开始的时候就被定义了,它被初始化到了每一次 loop 迭代时的当前元素中。 + +为什么 range(1, 3) 中的 i 只循环了两次而不是三次? range() 函数只处理从第一个到最后一个数,但不包括最后一个数,所以它在 2 就结束了。这是这类循环的通用做法。 + +element.append() 的作用是什么?它只是把东西追加到列表的末尾。打开 Python shell 然后创建一个新列表。任何时候当你遇到类似的用法,试着多玩几次,去体会它们的作用。 + + +### while语句 +现在我们来看一个新的循环: while-loop。只要一个布尔表达式是 True,while-loop 就会一直执行它下面的代码块。 + +等等,你应该能理解这些术语吧?如果我们写一行以 : 结尾的代码,它就会告诉 Python 开始一个新的代码块。我们用这种方式来结构化你的程序,以便 Python 明白你的意图。如果你还没有掌握这块内容,先回去复习一下,再做一些 if 语句、函数以及 for-loop,直到你掌握为止。 + +之后我们会做一些练习来训练你的大脑读取这些结构,就像我们训练你掌握布尔表达式一样。 + +回到 while-loop,它所做的只是像 if 语句一样的测试,但是它不是只运行一次代码块,而是在 while 是对的地方回到顶部再重复,直到表达式为 False。 + +但是 while-loop 有个问题:有时候它们停不下来。如果你的目的是让程序一直运行直到宇宙的终结,那这样的确很屌。但大多数情况下,你肯定是需要你的循环最终能停下来的。 + +##### 为了避免这些问题,你得遵守一些规则: + +1、保守使用 while-loop,通常用 for-loop 更好一些。 +2、检查一下你的 while 语句,确保布尔测试最终会在某个点结果为 False。 +3、当遇到问题的时候,把你的 while-loop 开头和结尾的测试变量打印出来,看看它们在做什么。 +在这个练习中,你要通过以下三个检查来学习 while-loop: + +```python +1 i = 0 +2 numbers = [] +3 +4 while i < 6: +5 print(f"At the top i is {i}") +6 numbers.append(i) +7 +8 i = i + 1 +9 print("Numbers now: ", numbers) +10 print(f"At the bottom i is {i}") +11 +12 +13 print("The numbers: ") +14 +15 for num in numbers: +16 print(num) +``` + +##### 运行结果 + +```python +At the top i is 0 +Numbers now: [0] +At the bottom i is 1 +At the top i is 1 +Numbers now: [0, 1] +At the bottom i is 2 +At the top i is 2 +Numbers now: [0, 1, 2] +At the bottom i is 3 +At the top i is 3 +Numbers now: [0, 1, 2, 3] +At the bottom i is 4 +At the top i is 4 +Numbers now: [0, 1, 2, 3, 4] +At the bottom i is 5 +At the top i is 5 +Numbers now: [0, 1, 2, 3, 4, 5] +At the bottom i is 6 +The numbers: +0 +1 +2 +3 +4 +5 +``` + + +##### 附加练习 +1、把这个 while-loop 转换成一个你可以调用的函数,然后用一个变量替代 i < 6 里面的 6。 +2、用这个函数重新写一下这个脚本,试试不同的数值。 +3、再增加一个变量给这个函数的参数,然后改变第 8 行的 +1,让它增加的值与之前不同。 +4、用这个函数重新写这个脚本,看看会产生什么样的效果。 +5、用 for-loop 和 range 写这个脚本。你还需要中间的增加值吗?如果不去掉这个增加值会发生什么? +任何时候你在运行程序的时候它失控了,只用按下 CTRL-C ,程序就会终止。 + + +##### 常见问题 +for-loop 和 while-loop 的区别是什么? for-loop 只能迭代(循环)一些东西的集合,而 while-loop 能够迭代(循环)任何类型的东西。不过,while-loop 很难用对,而你通常能够用 for-loop 完成很多事情。 + +循环好难,我应该如何理解它们?人们不理解循环的主要原因是他们跟不上代码的运行。当一个循环运行的时候,它会过一遍代码块,到结尾之后再跳到顶部。为了直观表现这个过程,你可以用 print 打印出循环的整个过程,把 print 行写在循环的前面、顶部、中间、结尾。研究一下输出的内容,试着理解它是如何运行的。 + +### 分支和函数 +目前为止你已经了解了 if 语句,函数以及列表。现在是时候深入学习一下了。照例输入如下代码,看看你能否明白程序在做什么。 + +```python +1 from sys import exit +2 +3 def gold_room(): +4 print("This room is full of gold. How much do you take?") +5 +6 choice = input("> ") +7 if "0" in choice or "1" in choice: +8 how_much = int(choice) +9 else: +10 dead("Man, learn to type a number.") +11 +12 if how_much < 50: +13 print("Nice, you're not greedy, you win!") +14 exit(0) +15 else: +16 dead("You greedy bastard!") +17 +18 +19 def bear_room(): +20 print("There is a bear here.") +21 print("The bear has a bunch of honey.") +22 print("The fat bear is in front of another door.") +23 print("How are you going to move the bear?") +24 bear_moved = False +25 +26 while True: +27 choice = input("> ") +28 +29 if choice == "take honey": +30 dead("The bear looks at you then slaps your face") +31 elif choice == "taunt bear" and not bear_moved: +32 print("The bear has moved from the door.") +33 print("You can go through it now.") +34 bear_moved = True +35 elif choice == "taunt bear" and bear_moved: +36 dead("The bear gets pissed off and chews your leg.") +37 elif choice == "open door" and bear_moved: +38 gold_room() +39 else: +40 print("I got no idea what that means.") +41 +42 +43 def cthulhu_room(): +44 print("Here you see the great evil Cthulhu.") +45 print("He, it, whatever stares at you and you go insane.") +46 print("Do you flee for your life or eat your head?") +47 +48 choice = input("> ") +49 +50 if "flee" in choice: +51 start() +52 elif "head" in choice: +53 dead("Well that was tasty!") +54 else: +55 cthulhu_room() +56 +57 +58 def dead(why): +59 print(why, "Good job!") +60 exit(0) +61 +62 def start(): +63 print("You are in a dark room.") +64 print("There is a door to your right and left.") +65 print("Which one do you take?") +66 +67 choice = input("> ") +68 +69 if choice == "left": +70 bear_room() +71 elif choice == "right": +72 cthulhu_room() +73 else: +74 dead("You stumble around the room until you starve.") +75 +76 +77 start() +``` + +##### 运行结果 + +```python +You are in a dark room. +There is a door to your right and left. Which one do you take? +> left +There is a bear here. +The bear has a bunch of honey. +The fat bear is in front of another door. How are you going to move the bear? +> taunt bear +The bear has moved from the door. You can go through it now. +> open door +This room is full of gold. How much do you take? +> 1000 +You greedy bastard! Good job! +``` + +##### 附加练习 +1、画一个这个游戏的流程图,并指出它是如何运转的。 +2、修正你的错误,包括拼写和语法错误。 +3、为你不理解的函数写上注释。 +4、为游戏增加一些功能,同时使代码更加简化。 +5、这个 gold_room 让你输入数字的方式有点奇怪。这样做有哪些 bug ?你能改善我的代码吗?可以查查看 int() 的相关知识。 + +##### 常见问题 +救命! 这个程序是怎么工作的!? 当你遇到不理解的代码时,不要着急,只要在每行代码下面写下注释,弄清楚这一行是做什么的,就很容易明白。确保你的注释和代码一样简洁。 然后要么画图,要么写一段话来描述代码是如何运行的。这样你就会理解其背后的原理。 + +为什么你要用 while True? 这样可以构建一个无限循环。 + +exit(0) 是干什么用的? 在很多操作系统中,一个程序可以用 exit(0) 来结束,其中传入的数字代表是否有错误。如果你用 exit(1) 代表有 1 个错误, exit(0) 则代表程序正常退出。它不同于通常的布尔逻辑(0==False),因为你可以用不同的数字来表示不同的错误结果。你可以用 exit(100) 来表示与 exit(2) 或者 exit(1) 不同的错误结果。 + +为什么 input() 有时会被写成 input('> ')? input 的参数是一个字符串,所以要在获取用户输入的内容前面加一个提示符。这里 > 也可以换成想要提示用户的文字。 + + + + + + diff --git a/PythonThinking/task7-面向对象的编程.md b/PythonThinking/task7-面向对象的编程.md new file mode 100644 index 0000000..fadc559 --- /dev/null +++ b/PythonThinking/task7-面向对象的编程.md @@ -0,0 +1,152 @@ +# 5、面向对象的编程 +Python 是一门“面向对象的编程语言”(Object Oriented Programming)。这是指 Python 中有一个叫做 类(class)的结构,能够让你用一种特定的方式结构化你的软件。通过使用类,你可以让你的程序保持连贯性,使用起来更清晰。至少理论上是这样。 + +## 类的例子 +```python +1 class Song(object): #class表示要创建类,Song是类的名称, +2 +3 def __init__(self, lyrics): #称为构造方法,根据类创建对象时自动执行 +4 self.lyrics = lyrics +#根据类 Song 创建对象 +#自动执行Song类的 __init__方法 +5 +6 def sing_me_a_song(self): #定义sing_me_a_song函数 +7 for line in self.lyrics: #采用for循环获取每一句歌词 +8 print(line) #打印出来 +9 +10 happy_bday = Song(["Happy birthday to you", +11 "I don't want to get sued", +12 "So I'll stop right there"]) +13 +14 bulls_on_parade = Song(["They rally around tha family", +15 "With pockets full of shells"]) +16 +17 happy_bday.sing_me_a_song() +18 +19 bulls_on_parade.sing_me_a_song() +``` + +##### 运行结果 + +```python +Happy birthday to you +I don't want to get sued +So I'll stop right there +They rally around tha family +With pockets full of shells +``` +##### 附加练习 +1、用这个方法再写一些歌,确保你明白你正在用字符列表来传歌词。 +2、把歌词放在一个单独的变量里,然后把这个变量放在类里面来使用。 +3、如果你能搞定这些,可以用它来做更多的事情。要是你现在没什么想法也别担心,就试试看会发生什么。然后把它们掰开、揉碎、反复研究。 +4、在网上搜搜“面向对象的编程”,然后填满你的大脑。别担心你看不懂,因为几乎一半的东西我也看不懂。 +##### 常见问题 +为什么我在类下面用 __init__ 函数或者其他函数的时候要用 self ? 如果你不用 self,那么像 cheese = 'Frank' 这样的代码就会很含糊,计算机不知道你是指实例的 cheese 属性还是 一个叫做 cheese 的局部变量。而用 self.cheese = 'Frank' 的话就会很清晰,你是指实例的属性 self.cheese 。 + +### 学着去说面向对象 +在这个练习中,我要教你如何去说“面向对象”。我所做的就是给你一些你需要了解的词和定义。然后我会给出一些需要填空的句子让你去理解。最后,你要完成一个大练习,从而在大脑中巩固这些句子。 + +#### 词汇训练 +(注:为了方便理解,定义保留英文原文。) + +类(class) :告诉 Python 创建一个新类型的东西(Tell Python to make a new type of thing)。 + +对象(object)两种含义:最基本类型的东西, 任何实例。(the most basic type of thing, and any instance of something.) + +实例(instance) :当你告诉 Python 创建一个类的时候你所得到的东西。(What you get when you tell Python to create a class.) + +def :你如何在类里面定义一个函数。(How you define a function inside a class.) + +self :在一个类的函数里面,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.”) + +花点时间为这些术语做一些闪词卡(flash cards)并记住它们,虽然在你完成这个练习之前单纯的记忆没有任何意义,但你必须要先了解这些基础的词汇。 + +#### 短语训练 +接下来是一些 Python 代码片段以及右边的解释。 + +class X(Y) : +创建一个名为 X 并继承自 Y 的类。 +(“Make a class named X that is-a Y.”) + +class X(object): def __init__(self, J) +类 X 有一个带有 self 和 J 参数的 __init__ 函数。 +(“class X has-a __init__ that takes self and J parameters.”) + +class X(object): def M(self, J): +类 X 有一个带有 self 和 J 参数的 M 函数。 +(“class X has-a function named M that takes self and J parameters.”) + +foo = X(): +设 foo 为类 X 的一个实例。 +(“Set foo to an instance of class X.”) + +foo.M(J) +从 foo 那里获取 M 函数,并用 self 和 J 参数来调用它。 +(“From foo, get the M function, and call it with parameters self, J.”) + +foo.K = Q +从 foo 那里获取 K 属性,并设它为 Q。 +(“From foo, get the K attribute, and set it to Q.”) + +在上述每一句中,当你看到 X, Y, M, J, K, Q, 以及 foo, 你可以把它们当做空格,比如,我还可以把这些句子写成: + +1.“Make a class named ??? that is-a Y.” +(创建一个名为 ??? 的类,它继承自 Y。) + +2.“class ??? has-a __init__ that takes self and ??? parameters.” +(类 ??? 有一个带了 self 和 ??? 参数的 __init__。) + +3.“class ??? has-a function named ??? that takes self and ??? parameters.” +(类 ??? 有一个名为 ??? 的函数,这个函数带有 self 和 ??? 两个参数。) + +4.“Set foo to an instance of class ???.” +(设 foo 为类 ??? 的一个实例。) + +5.“From foo, get the ??? function, and call it with self=??? and parameters ???.” +(从 foo 那里获取 ??? 函数,并用 self=??? 以及参数 ??? 来调用它。) + +6.“From foo, get the ??? attribute, and set it to ???.” +(从 foo 那里获取 ??? 属性,把它设为 ???。) + +同样地,把这些短语写到一些闪词卡上,然后记一记。把 Python 代码片段放在正面,解释的句子放在背面,你必须每次都正确说出每一个短语的意思。不是说得类似就行,而是要一模一样。 + +##### 综合训练 +最后一项准备工作是把词汇训练和短语训练结合在一起,以下是训练内容: + +1、做一个短语卡然后练习记忆。 + +2、把它翻过来,读句子,如果在句子中看到词汇训练中的词汇,就找到相应的词汇卡片。 + +3、练习记忆这些词汇卡片。 + +4、坚持练习,要是你感到有些累,就休息一下再继续。 + +#### 读更多代码 +你现在需要继续读更多的代码,并在这些代码中复习你之前学过的短语。试着找到尽可能多的包含类的文件,然后跟着如下要求去做: + +1、给出每个类的名字,以及其他的类从它那里继承了什么。 + +2、在每个类下面,列出它所拥有的函数以及它们的参数。 + +3、列出所有它用 self 使用的属性。 + +4、对于每个属性,给出它继承自哪个类。 + +这些练习的目的是过一遍真实的代码,并试着把你学过的短语和它们的用法匹配和关联起来。如果你做足了训练,你会开始看到这些匹配模式(match patterns)呼之欲出,而不再是一些你不明白的空格或字符。 + + + + + +