本 Wiki 开启了 HTTPS。但由于同 IP 的 Blog 也开启了 HTTPS,因此本站必须要支持 SNI 的浏览器才能浏览。为了兼容一部分浏览器,本站保留了 HTTP 作为兼容。如果您的浏览器支持 SNI,请尽量通过 HTTPS 访问本站,谢谢!
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录前一修订版 | |||
cs:programming:python:courses:gtx_cs1301x:chpt_3 [2024/01/14 13:59] – 移除 - 外部编辑 (未知日期) 127.0.0.1 | cs:programming:python:courses:gtx_cs1301x:chpt_3 [2024/01/14 13:59] (当前版本) – ↷ 页面cs:fundamental:gtx_cs1301x:chpt_3被移动至cs:programming:python:courses:gtx_cs1301x:chpt_3 codinghare | ||
---|---|---|---|
行 1: | 行 1: | ||
+ | ======Control Structures====== | ||
+ | //Chapter 3 notes// | ||
+ | ---- | ||
+ | ====Control Structures==== | ||
+ | * 控制程序执行流程的代码 | ||
+ | ===Conditionals=== | ||
+ | * 基于逻辑表达式选择不同的执行方式 | ||
+ | * if / else | ||
+ | ==indentation and conditionals== | ||
+ | * python 中所有具有相同缩进的代码被视作同一个 block 下的代码 | ||
+ | * 缩进也可以嵌套 | ||
+ | * Loops | ||
+ | * Functions | ||
+ | * Exceptions | ||
+ | ===scope=== | ||
+ | * scope 指在程序执行中使变量可见的区域 | ||
+ | * 编译性语言和解释性语言有所不同 | ||
+ | * scope 通过 control structure 来体现 | ||
+ | * conditional 不能保证自身运行,因此其内部的变量不能对外部可见 | ||
+ | * function 内部的变量对外部不可见 | ||
+ | ==scope in python== | ||
+ | * python 中的变量 scope 从变量创建的一刻开始 | ||
+ | * 该变量需要到下一行才能使用(不能创建中使用自身) | ||
+ | ==if / else in python== | ||
+ | * 条件语句下的 block 会接一个 '':'' | ||
+ | ===condition & boolean operators=== | ||
+ | * 可以通过 boolean 表达式来制定条件 | ||
+ | * boolean 表达式可以接受返回 boolean 的 function | ||
+ | * boolean 运算符可以用于连接多个表达式 | ||
+ | ==使用 member op 作为条件表达式== | ||
+ | 可以通过 '' | ||
+ | <code py> | ||
+ | club_members = [" | ||
+ | my_name = " | ||
+ | if my_name in club_members: | ||
+ | print(" | ||
+ | </ | ||
+ | '' | ||
+ | <code py> | ||
+ | mystery_string = " | ||
+ | if " | ||
+ | do sth.... | ||
+ | </ | ||
+ | ==使用 function 作为条件表达式== | ||
+ | <code py> | ||
+ | #isdigit() is an member function of string that used as the condition | ||
+ | myNumericString = " | ||
+ | if myNumericString.isdigit(): | ||
+ | prtin(" | ||
+ | </ | ||
+ | ==scope 与 condition== | ||
+ | * 条件语句不运行的前提下,其 block 下的 scope 是不存在的。因此所有在该 scope 内部的变量都不存在。 | ||
+ | * 推荐在条件语句外部创建 scope (minimun level) | ||
+ | ====Loops==== | ||
+ | * Loop: A programming control structure that executes a segment of code multiple times. | ||
+ | * For loops: | ||
+ | * Foreach: 自动循环容器中的所有内容(而不用手动指定循环次数) | ||
+ | * While loops: A single execution of a repeated task or** block of code**. | ||
+ | * do while: run at least once, then check the condition | ||
+ | ===For loop=== | ||
+ | ==For Loops in Python== | ||
+ | 基本写法: | ||
+ | <code py> | ||
+ | for i in range(1, 11): | ||
+ | print(i) | ||
+ | </ | ||
+ | '' | ||
+ | <code py> | ||
+ | #0 - 9, implicitly | ||
+ | range(10) | ||
+ | #0 - 9, explicitly | ||
+ | range (0 , 10) | ||
+ | #0, 2, 4, 6, 8 | ||
+ | range(0, 10, 2) | ||
+ | #count down(reverse) 10 - 1 | ||
+ | range(10, 1, -1) | ||
+ | </ | ||
+ | ==Primer on Indices== | ||
+ | * 循环适用于长得像 list 一样的主体k | ||
+ | * 循环,index 的起点是 '' | ||
+ | ==for each loop== | ||
+ | for each loop 与 for loop 类似。但相比 for loop,for each 使用变量(list)来作为范围,for each loop 会循环 list 中所有的元素。比如: | ||
+ | <code py> | ||
+ | listOfNumbers = [1,2,3,4,5] | ||
+ | for i in listOfNumbers: | ||
+ | sum += i | ||
+ | </ | ||
+ | 这个等同于如下的 for loop: | ||
+ | <code py> | ||
+ | for i in range(0, len(listOfNumbers)): | ||
+ | sum += i | ||
+ | </ | ||
+ | python 中,string 也可以作为范围变量;for each 访问的是 string 中的每一个字母: | ||
+ | <code py> | ||
+ | mystring = " | ||
+ | for char in mystring: | ||
+ | do sth | ||
+ | </ | ||
+ | ===While Loop=== | ||
+ | While Loop 适用于我们不清楚循环要进行多少次的情况下。 | ||
+ | ==python 的随机数== | ||
+ | <code py> | ||
+ | import random | ||
+ | |||
+ | # Returns a random integer greater than or equal to min and less than or equal to max. | ||
+ | random.randint(min, | ||
+ | </ | ||
+ | ==nested loop== | ||
+ | 使用 nested loop 统计 list string 中有多少词: | ||
+ | * 使用空格作为词数的技术 | ||
+ | * 在最后加上整个 list string 的长度补足未计数的部分 | ||
+ | <code py> | ||
+ | list_of_strings = ["This is the 1st string", | ||
+ | " | ||
+ | " | ||
+ | |||
+ | space_count = 0 | ||
+ | |||
+ | for current_string in list_of_strings: | ||
+ | for curr_char in current_string: | ||
+ | if curr_char == " ": | ||
+ | space_count += 1 | ||
+ | |||
+ | word_counts = space_count + len(list_of_strings) | ||
+ | print(word_counts) | ||
+ | </ | ||
+ | ===相关概念=== | ||
+ | ==重要的 loop 关键字== | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | ==scope & loop== | ||
+ | * loop 中创建的变量会在下一次迭代中被重新初始化。如果不希望被重置,把变量放到循环外部。 | ||
+ | ====Functions==== | ||
+ | * **Function**: | ||
+ | ==什么是 call 和 definitaion== | ||
+ | * **Function Call**: A **place** where a **function is actually used** in some code. | ||
+ | *** Function Definition**: | ||
+ | * **Function Header**: The name and list of parameters a function expects, provided as reference to the rest of the program to use when calling the function. | ||
+ | * **name** | ||
+ | * **Parameter**: | ||
+ | *** Function Body**: The code that a function runs when called. | ||
+ | * **Return Statemen**t: | ||
+ | ==call 的过程== | ||
+ | * 给 function paramater 使用的**值**被称为 Arguments。可以将 parameter 视作 variable, Arguments 视作具体值。 | ||
+ | * 需要注意的三点: | ||
+ | * how to call | ||
+ | * what input will be given | ||
+ | * what output to expect(某些 call 不会返回值) | ||
+ | ===function in python=== | ||
+ | ==定义 function== | ||
+ | <code py> | ||
+ | #defination | ||
+ | def printYen(): | ||
+ | print(" | ||
+ | |||
+ | # call | ||
+ | printYen() | ||
+ | </ | ||
+ | <WRAP center round important 100%> | ||
+ | python 中必须先定义函数再使用。 | ||
+ | </ | ||
+ | ==parameter & returns == | ||
+ | <code py> | ||
+ | # return | ||
+ | def returnYen(): | ||
+ | return " | ||
+ | |||
+ | # using parameter | ||
+ | def returnYenAmount(amount): | ||
+ | return " | ||
+ | print(returnYenAmount(5)) | ||
+ | </ | ||
+ | <WRAP center round info 100%> | ||
+ | return 会直接终止当前 function body 的继续运行 | ||
+ | </ | ||
+ | ==注意事项== | ||
+ | * **not** to use the **same variable names** in your parameter list that you use in the rest of your program | ||
+ | * always make sure to check full_results.txt | ||
+ | ==常见错误== | ||
+ | * Parameter Mismatch:argument 和 parameter 的数量不同,或是参数不匹配。 | ||
+ | * Scope Error: | ||
+ | * 函数内部的变量的 scope 只处于函数内部。 | ||
+ | ==None== | ||
+ | * 如果函数不返回任何值,那么返回 None | ||
+ | * 需要确保每个 conditional 中都有正确的 return (包括 nested conditional) | ||
+ | * 循环结束时可能没有成功匹配条件,因此需要在 loop 结束后手动 return | ||
+ | ==keyword parameters== | ||
+ | keyword prarameter 指函数中的自带的,用于实现某种特殊功能的**可选**参数(可忽略)。比如 '' | ||
+ | <code py> | ||
+ | #sep is the character between string A and string B | ||
+ | #end is the character added at the end of the printed string | ||
+ | #output will be A#B! | ||
+ | # by default, sep = space, end = newline | ||
+ | print(" | ||
+ | </ | ||
+ | keyword parameter 处于所有函数 parameter 的后方,可以自定义;功能类似 C++ 的函数默认值。比如: | ||
+ | <code py> | ||
+ | #currency has default value USD | ||
+ | def currencyAmount(amount, | ||
+ | #when calling, currency can be changed by signing an parameter to it | ||
+ | currencyAmount(5, | ||
+ | </ | ||
+ | ====Exception Handling==== | ||
+ | * Exception Handling 针对的是**某些可以预期**的问题。这些问题通常不重要,但有时会影响到用户的使用体验。Exception Handling 可以尽可能的使用户避免这些问题。 | ||
+ | ==catching” Errors== | ||
+ | * 如果 error 没有被捕获(uncaught error),很可能导致程序崩溃 | ||
+ | * 对 error 进行捕获 (catching error) 可以避免程序的崩溃 | ||
+ | <WRAP center round info 100%> | ||
+ | catching error 与通常避免错误的处理方式不同。通常的处理的方式是**阻止错误**的发生;比如不允许除零的行为,来保证程序的正常运行。而 catching error 是对 error 做处理,**保证遭遇错误的时候程序依然能够正常运行**:比如当用户进行除零的行为时,catching error 首先告诉电脑**不要 crash**,其次再通过电脑告知用户除零这种操作是不允许的。 | ||
+ | </ | ||
+ | ==Catch Error 的优势== | ||
+ | - 对于独立的 function, catching error 允许我们首先考虑 code 本身的功能,在之后再去考虑可能产生什么样的 error | ||
+ | * catching error 的方式可以允许程序执行一部分直到错误的出现 | ||
+ | - 相比把所有错误检测的条件语句放到程序之前,catch error 将所有 error 的处理放到最后,使程序更易读 | ||
+ | - catching error 可以在遭遇**未知错误**的时候阻止程序 crash | ||
+ | |||
+ | ===Try-Catch-Finally=== | ||
+ | * The **Try** statement marks a block of code to attempt, but in which we anticipate an error might arise. | ||
+ | * The **Catch** statement names the errors to anticipate, and marks a block of code to run if an anticipated error arises. (Python often refers to this as the **Except** block as well.) | ||
+ | * The **Finally** statement marks a block of code to run after the above two blocks no matter what. | ||
+ | <WRAP center round box 100%> | ||
+ | Try block 中的代码是试错用的, catch 是处理 error 用的 ,Final 中的代码是之前两步完成以后一定会运行的代码(应该放一些比较稳当的代码) | ||
+ | </ | ||
+ | ===Try and Except=== | ||
+ | 在 python 中, try-catch 以 '' | ||
+ | <code py> | ||
+ | try: | ||
+ | print(" | ||
+ | myInt = int(myString) | ||
+ | print(myInt) | ||
+ | except: | ||
+ | pass | ||
+ | print(done) | ||
+ | </ | ||
+ | |||
+ | <WRAP center round box 100%> | ||
+ | 需要注意的是,如果 try block 中有任意错误出现,那么代码会直接跳转到之后的 except block 中;try block 之后的语句都不会执行。相反,如果 try block 中的语句没有出现错误,那么 except block 永远不会执行。 | ||
+ | </ | ||
+ | ==指定 except block 中的内容== | ||
+ | execpt block 中可以指定对错误内容的反馈(log),比如: | ||
+ | <code py> | ||
+ | try: | ||
+ | print(" | ||
+ | myInt = int(myString) | ||
+ | print(myInt) | ||
+ | except: | ||
+ | print(" | ||
+ | </ | ||
+ | ==指定需要捕获的 error== | ||
+ | python 中允许我们对指定类型的 error 进行捕获,比如: | ||
+ | <code py> | ||
+ | try: | ||
+ | print(1 / 0) | ||
+ | print(" | ||
+ | except ZeroDivisionError: | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | 这里的 '' | ||
+ | \\ \\ | ||
+ | 但需要注意的是,这种情况下,python 只能捕获 except block 中指定的错误类型。如果出现了别的类型的错误,python 会: | ||
+ | - 按通常一样,跳转到 except block | ||
+ | - 寻找是否存在与该错误类型对应的 block | ||
+ | - 如果没有找到,那么该程序会 crash | ||
+ | ==使用变量存储错误信息== | ||
+ | 如果我们希望看到一些额外的,关于错误如何抛出的信息,我们可以使用 '' | ||
+ | <code py> | ||
+ | try: | ||
+ | print(1 / 0) | ||
+ | except ZeroDivisionError as error: | ||
+ | print(error) # variable error stores error info from ZeroDivisionError | ||
+ | print(" | ||
+ | </ | ||
+ | 此处的 '' | ||
+ | <code py> | ||
+ | division by zero | ||
+ | Done! | ||
+ | </ | ||
+ | ==同时处理多种 error== | ||
+ | python 提供了同时处理多种 error 的机制: | ||
+ | <code py> | ||
+ | try: | ||
+ | print(" | ||
+ | print(1 / 0) | ||
+ | except ZeroDivisionError: | ||
+ | print(" | ||
+ | except TypeError: | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | 可以注意到, '' | ||
+ | <code bash> | ||
+ | A TypeError occurred! | ||
+ | Done! | ||
+ | </ | ||
+ | 需要注意的是,即便同时存在多种类型的错误,只要成功捕获了一个错误,python 就会执行对应的 except block 中的内容,以及 except block 之后的内容了。即便是 try 中还存在着其他类型的错误,python 也不会在进行执行,比如: | ||
+ | <code py> | ||
+ | try: | ||
+ | print(" | ||
+ | myInt = int(" | ||
+ | print(1 / 0) | ||
+ | |||
+ | except TypeError: | ||
+ | print(" | ||
+ | except ZeroDivisionError: | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | 这里的 '' | ||
+ | 如果需要对**其他剩余的错误**做一个总的处理,可以使用关键字 '' | ||
+ | <code py> | ||
+ | try: | ||
+ | myInt = int(" | ||
+ | print(" | ||
+ | print(1 / 0) | ||
+ | |||
+ | except TypeError as error: | ||
+ | print(error) | ||
+ | except ZeroDivisionError as error: | ||
+ | print(error) | ||
+ | except Exception as error: | ||
+ | print(error) | ||
+ | print(" | ||
+ | </ | ||
+ | 如果不指定具体打印内容,python 会自动根据具体的错误类型信息将错误打印出来: | ||
+ | < | ||
+ | Invalid literal for int() with base 10: 'This is string' | ||
+ | Done! | ||
+ | </ | ||
+ | ===Else and Finally=== | ||
+ | ==else 关键字== | ||
+ | '' | ||
+ | <code py> | ||
+ | mystery_value = 9 | ||
+ | |||
+ | try: | ||
+ | print( 10 / mystery_value) | ||
+ | except ZeroDivisionError: | ||
+ | print(" | ||
+ | except Exception: | ||
+ | print(" | ||
+ | else: | ||
+ | print(" | ||
+ | </ | ||
+ | 将打印: | ||
+ | <code py> | ||
+ | 1.1111111111111112 | ||
+ | No error found! | ||
+ | </ | ||
+ | <WRAP center round tip 100%> | ||
+ | else 关键字可能看起来有些多余。但实际上,因为这个关键字属于 except block 的一部分,而只有当所有 expect block 都没有执行,也就是没有错误被捕获的时候,else block 才会运行。因此,当 else block 中的语句被执行时,我们就可以百分之百的确认之前 try block 里的代码是没有(非逻辑)错误的。 | ||
+ | </ | ||
+ | ==else 的重要应用:读取文件== | ||
+ | 该应用由如下程序所示: | ||
+ | <code py> | ||
+ | try: | ||
+ | #open file in read only mode | ||
+ | input_file = open(" | ||
+ | except IOError as error: | ||
+ | print(" | ||
+ | else: | ||
+ | for line in input_file: | ||
+ | print lines | ||
+ | input_file.close() | ||
+ | </ | ||
+ | 该应用中,如果在打开 '' | ||
+ | ==Finally 关键字== | ||
+ | 无论 try block 中有没有内容被捕获,Finally block 中内容都会运行: | ||
+ | <code py> | ||
+ | try: | ||
+ | #open file in read only mode | ||
+ | input_file = open(" | ||
+ | except IOError as error: | ||
+ | print(" | ||
+ | else: | ||
+ | for line in input_file: | ||
+ | print lines | ||
+ | finally: | ||
+ | input_file.close() | ||
+ | </ | ||
+ | 这里的 '' | ||
+ | <WRAP center round help 100%> | ||
+ | **为什么不在 try block 后面直接加无论如何都想要运行的代码?** \\ \\ | ||
+ | finally 可以保证即便是 try block 中**出现无法处理的错误**(Uncaught Errors)的情况下,也能继续运行 finally block 内的语句。如果直接在 try block 后面添加语句,当出现 Uncaught Errors 时,程序会直接 crash,因此后面的语句也没有机会执行了。 | ||
+ | |||
+ | </ | ||
+ | ==使用嵌套的 try block 处理不同的错误== | ||
+ | 有如下代码: | ||
+ | <code py> | ||
+ | try: | ||
+ | #Open InputFile.txt in read-only mode | ||
+ | input_file = open(" | ||
+ | try: | ||
+ | #For each line in the file | ||
+ | for line in input_file: | ||
+ | #Print the line | ||
+ | print(int(line)) | ||
+ | #Catch a ValueError | ||
+ | except ValueError as error: | ||
+ | print(" | ||
+ | else: | ||
+ | print(" | ||
+ | finally: | ||
+ | #Close the file | ||
+ | input_file.close() | ||
+ | #Catch an IOError | ||
+ | except IOError as error: | ||
+ | print(" | ||
+ | </ | ||
+ | 这段代码中,我们的本意是先验证文件是否能正常打开,再验证文件的内容是否能正确的从 string 转化为 int。对此,我们可以使用嵌套的 try block 结构来处理。可以看到,外部的 try block 处理的是 IOError,而内部的 try block 处理的是 ValueError。几点需要注意的是: | ||
+ | * 当外部 try block 捕获匹配的内容时,会直接跳过其之后的内容到对应的**同级** except block 中。以本例为例子中,外部的 try block 并没有做 finally block 的处理。如果外部 try block 遇到 Uncaught Errors 时,内部的 finally block 中的语句时无法打印的。 | ||
+ | * 当内部的 try block 捕获错误时,其错误匹配按**由内而外**的顺序来搜寻。也就是: | ||
+ | * 优先查找同级 except block 中有没有匹配的错误处理 | ||
+ | * 如果没有,回到上级 try block 对应的 except block 中查找 | ||
+ | ==return 与 try block 的配合使用== | ||
+ | '' | ||
+ | <code py> | ||
+ | def return_file_text(filename): | ||
+ | try: | ||
+ | file = open(filename) | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | ===Error Handling and Control Structures=== | ||
+ | ==Error Handling and For Loops== | ||
+ | 如果 loop 出现问题就希望结束 loop,那么应该把 try block 包含整个 loop: | ||
+ | <code py> | ||
+ | try: | ||
+ | #For each line in the file | ||
+ | for line in input_file: | ||
+ | #Print the line | ||
+ | print(int(line)) | ||
+ | #Catch a ValueError | ||
+ | except ValueError as error: | ||
+ | print(" | ||
+ | </ | ||
+ | 如果希望对单次的 iteration 进行错误捕获,则应该把 try block 放到 loop 中: | ||
+ | |||
+ | <code py> | ||
+ | #For each line in the file | ||
+ | for line in input_file: | ||
+ | try: | ||
+ | #Print the line | ||
+ | print(int(line)) | ||
+ | #Catch a ValueError | ||
+ | except ValueError as error: | ||
+ | print(" | ||
+ | </ | ||
+ | 这样的结构只会在出现错误时打断当前的迭代,loop 还会继续执行剩余的部分。 | ||
+ | <WRAP center round info 100%> | ||
+ | 可以在 except block 中使用 break 语句强制结束循环 | ||
+ | </ | ||
+ | ==Error Handling and Functions== | ||
+ | * 如果 function 中出现错误,那么会首先查找 function 内部是否有 except block | ||
+ | * 如果没有,会跳转到外部 function 被调用的位置,查看该位置是否处于 try block 内部。如果处于,则查找是否存在对应的 except block。 |