What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
cs:programming:python:courses:gtx_cs1301x:chpt_3 [2024/01/14 13:59] – 移除 - 外部编辑 (未知日期) 127.0.0.1cs: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 作为条件表达式==
 +可以通过 ''in'' 成员查询条件是否属于某个条件集合:
 +<code py>
 +club_members = ["John", "Jenny", "Jason", "Jane"]
 +my_name = "Jenny"
 +if my_name in club_members:
 +    print("Welcome back!")
 +</code>
 +''in'' 关键字还可以用于匹配字符串,比如:
 +<code py>
 +mystery_string = "zizazzle"
 +if "zzz" in mystery_string = "zizazzle":
 +    do sth....
 +</code>
 +==使用 function 作为条件表达式==
 +<code py>
 +#isdigit() is an member function of string that used as the condition
 +myNumericString = "12345"
 +if myNumericString.isdigit():
 +    prtin("something")
 +</code>
 +==scope 与 condition==
 +  * 条件语句不运行的前提下,其 block 下的 scope 是不存在的。因此所有在该 scope 内部的变量都不存在。
 +  * 推荐在条件语句外部创建 scope (minimun level)
 +====Loops====
 +  * Loop: A programming control structure that executes a segment of code multiple times.
 +    * For loops:  A loop control structure that runs a block of code a **predetermined number of times.**
 +    * 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>
 +''range'' 是左闭右开区间 $[1,11)$。''range()'' 函数的几种初始化方法:
 +<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)
 +</code>
 +==Primer on Indices==
 +  * 循环适用于长得像 list 一样的主体k
 +  * 循环,index 的起点是 ''0''
 +==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
 +</code>
 +这个等同于如下的 for loop:
 +<code py>
 +for i in range(0, len(listOfNumbers)):
 +    sum += i
 +</code>
 +python 中,string 也可以作为范围变量;for each 访问的是 string 中的每一个字母:
 +<code py>
 +mystring = "abcde"
 +for char in mystring:
 +    do sth
 +</code>
 +===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, max)
 +</code>
 +==nested loop==
 +使用 nested loop 统计 list string 中有多少词:
 +  * 使用空格作为词数的技术
 +  * 在最后加上整个 list string 的长度补足未计数的部分
 +<code py>
 +list_of_strings = ["This is the 1st string", "This is the 2nd string", 
 +                   "This is the 3rd string", "This is the 4th string", 
 +                   "This is the 5tj 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)
 +</code>
 +===相关概念===
 +==重要的 loop 关键字==
 +  * ''continue'':跳过当前循环中迭代剩下的内容,跳到下一个迭代
 +  * ''pass'':使用 loop,但什么都不做(空语句)
 +  * ''break'':跳出所有的循环
 +==scope & loop==
 +  * loop 中创建的变量会在下一次迭代中被重新初始化。如果不希望被重置,把变量放到循环外部。
 +====Functions====
 +  * **Function**: A segment of code that performs a specific task, sometimes taking some input and sometimes returning some output.
 +==什么是 call 和 definitaion==
 +  * **Function Call**: A **place** where a **function is actually used** in some code.
 +  *** Function Definition**: A segment of code that creates a function, including its name, parameters, and code, to be used by other portions of a program.
 +    * **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**: A variable for which a function expects to receive a value when called, whose scope is the function’s own execution.
 +    *** Function Body**: The code that a function runs when called.
 +    * **Return Statemen**t: The line of code that defines what output will be sent back at the end of a function.
 +==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("$", end='')
 +
 +# call
 +printYen()
 +</code>
 +<WRAP center round important 100%>
 +python 中必须先定义函数再使用。
 +</WRAP>
 +==parameter & returns ==
 +<code py>
 +# return
 +def returnYen():
 +    return "Y"
 +
 +# using parameter
 +def returnYenAmount(amount):
 +    return "Y" + str(amount)
 +print(returnYenAmount(5))
 +</code>
 +<WRAP center round info 100%>
 +return 会直接终止当前 function body 的继续运行
 +</WRAP>
 +==注意事项==
 +  * **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 指函数中的自带的,用于实现某种特殊功能的**可选**参数(可忽略)。比如 ''print()''
 +<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("A", "B", sep = "#", end = "!")
 +</code>
 +keyword parameter 处于所有函数 parameter 的后方,可以自定义;功能类似 C++ 的函数默认值。比如:
 +<code py>
 +#currency has default value USD
 +def currencyAmount(amount, currency = "USD")
 +#when calling, currency can be changed by signing an parameter to it
 +currencyAmount(5, currency = "GBP")
 +</code>
 +====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**,其次再通过电脑告知用户除零这种操作是不允许的。
 +</WRAP>
 +==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 中的代码是之前两步完成以后一定会运行的代码(应该放一些比较稳当的代码)
 +</WRAP>
 +===Try and Except===
 +在 python 中, try-catch 以 ''try'' - ''except'' 关键字的形式存在。比如下列的例子:
 +<code py>
 +try:
 +    print("Converting myString to int....")
 +    myInt = int(myString)
 +    print(myInt)
 +except:
 +    pass
 +print(done)
 +</code>
 +
 +<WRAP center round box 100%>
 +需要注意的是,如果 try block 中有任意错误出现,那么代码会直接跳转到之后的 except block 中;try block 之后的语句都不会执行。相反,如果 try block 中的语句没有出现错误,那么 except block 永远不会执行。
 +</WRAP>
 +==指定 except block 中的内容==
 +execpt block 中可以指定对错误内容的反馈(log),比如:
 +<code py>
 +try:
 +    print("Converting myString to int....")
 +    myInt = int(myString)
 +    print(myInt)
 +except:
 +    print("Can't convert an non-number string to int")
 +</code>
 +==指定需要捕获的 error==
 +python 中允许我们对指定类型的 error 进行捕获,比如:
 +<code py>
 +try:
 +    print(1 / 0)
 +    print("No error occurred!")
 +except ZeroDivisionError:
 +    print("An error occurred!")
 +print("Done!")
 +</code>
 +这里的 ''print(1/0)'' 是 ''ZeroDivisionError'' 的错误类型,因此 ''except'' block 会成功匹配该错误,并执行该错误下的语句,这里是 ''print("An error occurred!")''
 +\\ \\ 
 +但需要注意的是,这种情况下,python 只能捕获 except block 中指定的错误类型。如果出现了别的类型的错误,python 会:
 +  - 按通常一样,跳转到 except block 
 +  - 寻找是否存在与该错误类型对应的 block
 +  - 如果没有找到,那么该程序会 crash
 +==使用变量存储错误信息==
 +如果我们希望看到一些额外的,关于错误如何抛出的信息,我们可以使用 ''as'' 关键字来存储该信息。写法如下:
 +<code py>
 +try:
 +    print(1 / 0)
 +except ZeroDivisionError as error:
 +    print(error) # variable error stores error info from ZeroDivisionError 
 +print("Done!")
 +</code>
 +此处的 ''error'' 变量可以为任何名字,存储的是 ''ZeroDivisionError'' 带来的信息 ''division by zero''。因此,打印结果为:
 +<code py>
 +division by zero
 +Done!
 +</code>
 +==同时处理多种 error==
 +python 提供了同时处理多种 error 的机制:
 +<code py>
 +try:
 +    print("String" + 1)
 +    print(1 / 0)
 +except ZeroDivisionError:
 +    print("A ZeroDivisionError occurred!")
 +except TypeError:
 +    print("A TypeError occurred!")
 +print("Done!")
 +</code>
 +可以注意到, ''print("String" + 1)'' 会导致 ''TypeError''. 当该错误出现时,python 会跳转到 except block 中,以**从上到下**的顺序寻找与该错误类型匹配的 except block。我们的程序中有对应 ''TypeError'' 的处理,因此会打印:
 +<code bash>
 +A TypeError occurred!
 +Done!
 +</code>
 +需要注意的是,即便同时存在多种类型的错误,只要成功捕获了一个错误,python 就会执行对应的 except block 中的内容,以及 except block 之后的内容了。即便是 try 中还存在着其他类型的错误,python 也不会在进行执行,比如:
 +<code py>
 +try:
 +    print("String" + 1)
 +    myInt = int("This is string")
 +    print(1 / 0)
 +
 +except TypeError:
 +    print("A TypeError occurred!")
 +except ZeroDivisionError:
 +    print("A ZeroDivisionError occurred!")
 +print("Done!")
 +</code>
 +这里的 ''myInt = int("This is string")'' 是 ''ValueError'' 类型的错误。按道理来说,由于我们没有提供对应的错误处理,程序应该 crash 掉。但实际上,在其执行之前已经出现了 ''TypeError'' 类型的错误,因此该行代码以及其之后的,在 try block 中的内容都不会执行。因此打印结果与之前的例子一样。\\ \\ 
 +如果需要对**其他剩余的错误**做一个总的处理,可以使用关键字 ''Exception'',比如
 +<code py>
 +try:
 +    myInt = int("This is string")
 +    print("String" + 1)
 +    print(1 / 0)
 +
 +except TypeError as error:
 +    print(error)
 +except ZeroDivisionError as error:
 +    print(error)
 +except Exception as error:
 +    print(error)
 +print("Done!")
 +</code>
 +如果不指定具体打印内容,python 会自动根据具体的错误类型信息将错误打印出来:
 +<code>
 +Invalid literal for int() with base 10: 'This is string'
 +Done!
 +</code>
 +===Else and Finally===
 +==else 关键字==
 +''else'' 关键字是 python 特有的一个机制。当所有其他 except block 中的内容都没有执行的时候(也就是 try block 中程序无错运行完毕的时候),python 会跳转到 else block 下的语句运行,比如:
 +<code py>
 +mystery_value = 9
 +
 +try:
 +    print( 10 / mystery_value)
 +except ZeroDivisionError:
 +    print("Can't divide by zero")
 +except Exception:
 +    print("Not possible")
 +else:
 +    print("No error found!")
 +</code>
 +将打印:
 +<code py>
 +1.1111111111111112
 +No error found!
 +</code>
 +<WRAP center round tip 100%>
 +else 关键字可能看起来有些多余。但实际上,因为这个关键字属于 except block 的一部分,而只有当所有 expect block 都没有执行,也就是没有错误被捕获的时候,else block 才会运行。因此,当 else block 中的语句被执行时,我们就可以百分之百的确认之前 try block 里的代码是没有(非逻辑)错误的。
 +</WRAP>
 +==else 的重要应用:读取文件==
 +该应用由如下程序所示:
 +<code py>
 +try:
 +    #open file in read only mode
 +    input_file = open("Fake.txt", mode = "r")
 +except IOError as error:
 +    print("An input error occurred!")
 +else:
 +    for line in input_file:
 +        print lines
 +    input_file.close()
 +</code>
 +该应用中,如果在打开 ''Fake.txt'' 的过程中出现了任何错误,都会被 python 捕获。如果打开正确,则会执行剩余的逐行读取操作(else block 中的部分)。
 +==Finally 关键字==
 +无论 try block 中有没有内容被捕获,Finally block 中内容都会运行:
 +<code py>
 +try:
 +    #open file in read only mode
 +    input_file = open("Fake.txt", mode = "r")
 +except IOError as error:
 +    print("An input error occurred!")
 +else:
 +    for line in input_file:
 +        print lines
 +finally:
 +    input_file.close()
 +</code>
 +这里的 ''input_file.close()'' 一定会被执行。
 +<WRAP center round help 100%>
 +**为什么不在 try block 后面直接加无论如何都想要运行的代码?** \\ \\ 
 +finally 可以保证即便是 try block 中**出现无法处理的错误**(Uncaught Errors)的情况下,也能继续运行 finally block 内的语句。如果直接在 try block 后面添加语句,当出现 Uncaught Errors 时,程序会直接 crash,因此后面的语句也没有机会执行了。
 +
 +</WRAP>
 +==使用嵌套的 try block 处理不同的错误==
 +有如下代码:
 +<code py>
 +try:
 +    #Open InputFile.txt in read-only mode
 +    input_file = open("FakeFile.txt", mode = "r")  
 +    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("A value error occurred!")
 +    else:
 +        print("No errors occurred converting the file!")
 +    finally:
 +        #Close the file
 +        input_file.close()
 +#Catch an IOError
 +except IOError as error:
 +    print("An error occurred reading the file!")
 +</code>
 +这段代码中,我们的本意是先验证文件是否能正常打开,再验证文件的内容是否能正确的从 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 的配合使用==
 +''return'' 可以终止函数的运行并返回结果。我们可以将这个功能放置在 except block 中来达到终止函数的运行并返回错误信息的效果:
 +<code py>
 +def return_file_text(filename):
 +     try:
 +         file = open(filename)
 +     except:
 +         return "Error opening file!"
 +     file_text = file.read()
 +     return file_text
 +</code>
 +===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("A value error occurred!")
 +</code>
 +如果希望对单次的 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("A value error occurred!")
 +</code>
 +这样的结构只会在出现错误时打断当前的迭代,loop 还会继续执行剩余的部分。
 +<WRAP center round info 100%>
 +可以在 except block 中使用 break 语句强制结束循环
 +</WRAP>
 +==Error Handling and Functions==
 +  * 如果 function 中出现错误,那么会首先查找 function 内部是否有 except block
 +  * 如果没有,会跳转到外部 function 被调用的位置,查看该位置是否处于 try block 内部。如果处于,则查找是否存在对应的 except block。