2020-8-15 Python語言基礎3:函式、面向物件、異常處理
阿新 • • 發佈:2020-08-15
函式
函式的簡介
# - 函式也是一個物件 # - 物件是記憶體中專門用來儲存資料的一塊區域 # - 函式可以用來儲存一些可執行的程式碼,並且可以在需要時,對這些語句進行多次的呼叫 # - 建立函式: # # def 函式名([形參1, 形參2, ...形參n]): # 程式碼塊 # # # - 函式名必須要符號識別符號的規範 # (可以包含字母、數字、下劃線、但是不能以數字開頭) # - 函式中儲存的程式碼不會立即執行,需要呼叫函式程式碼才會執行 # - 呼叫函式: # 函式物件() # - 定義函式一般都是要實現某種功能的 # 比如有如下三行程式碼,這三行程式碼是一個完整的功能 # print('Hello') # print('你好') # print('再見') # 定義一個函式 def fn() : print('這是我的第一個函式!') print('hello') print('今天天氣真不錯!') # 列印fn # print(fn) <function fn at 0x03D2B618> # print(type(fn)) <class 'function'> # fn是函式物件 fn()呼叫函式 # print是函式物件 print()呼叫函式 # fn() # 定義一個函式,可以用來求任意兩個數的和 # def sum() : # a = 123 # b = 456 # print(a + b) # sum() # 定義函式時指定形參 def fn2(a , b) : # print('a =',a) # print('b =',b) print(a,"+",b,"=",a + b) # 呼叫函式時,來傳遞實參 fn2(10,20) fn2(123,456)
函式的引數
# - 在定義函式時,可以在函式名後的() # 中定義數量不等的形參, # 多個形參之間使用, 隔開 # - 形參(形式引數),定義形參就相當於在函式內部聲明瞭變數,但是並不賦值 # - 實參(實際引數) # - 如果函式定義時,指定了形參,那麼在呼叫函式時也必須傳遞實參, # 實參將會賦值給對應的形參,簡單來說,有幾個形參就得傳幾個實參 # # - 練習1: # 定義一個函式,可以用來求任意三個數的乘積 # 求任意三個數的乘積 def mul(a,b,c): print(a*b*c) # - 練習2: # 定義一個函式,可以根據不同的使用者名稱顯示不同的歡迎資訊 # 根據不同的使用者名稱顯示不同的歡迎資訊 def welcome(username): print('歡迎',username,'光臨') # mul(1,2,3) # welcome('孫悟空') # 定義一個函式 # 定義形參時,可以為形參指定預設值 # 指定了預設值以後,如果使用者傳遞了引數則預設值沒有任何作用 # 如果使用者沒有傳遞,則預設值就會生效 def fn(a = 5 , b = 10 , c = 20): print('a =',a) print('b =',b) print('c =',c) # fn(1 , 2 , 3) # fn(1 , 2) # fn() # 實參的傳遞方式 # 位置引數 # 位置引數就是將對應位置的實參複製給對應位置的形參 # 第一個實參賦值給第一個形參,第二個實參賦值給第二個形參 。。。 # fn(1 , 2 , 3) # 關鍵字引數 # 關鍵字引數,可以不按照形參定義的順序去傳遞,而直接根據引數名去傳遞引數 # fn(b=1 , c=2 , a=3) # print('hello' , end='') # 位置引數和關鍵字引數可以混合使用 # 混合使用關鍵字和位置引數時,必須將位置引數寫到前面 # fn(1,c=30) def fn2(a): print('a =',a) # 函式在呼叫時,解析器不會檢查實參的型別 # 實參可以傳遞任意型別的物件 b = 123 b = True b = 'hello' b = None b = [1,2,3] # fn2(b) fn2(fn) def fn3(a , b): print(a+b) # fn3(123,"456") def fn4(a): # 在函式中對形參進行重新賦值,不會影響其他的變數 # a = 20 # a是一個列表,嘗試修改列表中的元素 # 如果形參執行的是一個物件,當我們通過形參去修改物件時 # 會影響到所有指向該物件的變數 a[0] = 30 print('a =',a,id(a)) c = 10 c = [1,2,3] # fn4(c) # fn4(c.copy()) # fn4(c[:]) # print('c =',c,id(c))
不定長引數
# 不定長的引數 # 定義一個函式,可以求任意個數字的和 def sum(*nums): # 定義一個變數,來儲存結果 result = 0 # 遍歷元組,並將元組中的數進行累加 for n in nums : result += n print(result) # sum(123,456,789,10,20,30,40) # 在定義函式時,可以在形參前邊加上一個*,這樣這個形參將會獲取到所有的實參 # 它將會將所有的實參儲存到一個元組中 # a,b,*c = (1,2,3,4,5,6) # *a會接受所有的位置實參,並且會將這些實參統一儲存到一個元組中(裝包) def fn(*a): print("a =",a,type(a)) # fn(1,2,3,4,5) # 帶星號的形參只能有一個 # 帶星號的引數,可以和其他引數配合使用 # 第一個引數給a,第二個引數給b,剩下的都儲存到c的元組中 # def fn2(a,b,*c): # print('a =',a) # print('b =',b) # print('c =',c) # 可變引數不是必須寫在最後,但是注意,帶*的引數後的所有引數,必須以關鍵字引數的形式傳遞 # 第一個引數給a,剩下的位置引數給b的元組,c必須使用關鍵字引數 # def fn2(a,*b,c): # print('a =',a) # print('b =',b) # print('c =',c) # 所有的位置引數都給a,b和c必須使用關鍵字引數 # def fn2(*a,b,c): # print('a =',a) # print('b =',b) # print('c =',c) # 如果在形參的開頭直接寫一個*,則要求我們的所有的引數必須以關鍵字引數的形式傳遞 def fn2(*,a,b,c): print('a =',a) print('b =',b) print('c =',c) # fn2(a=3,b=4,c=5) # *形參只能接收位置引數,而不能接收關鍵字引數 # def fn3(*a) : # print('a =',a) # **形參可以接收其他的關鍵字引數,它會將這些引數統一儲存到一個字典中 # 字典的key就是引數的名字,字典的value就是引數的值 # **形參只能有一個,並且必須寫在所有引數的最後 def fn3(b,c,**a) : print('a =',a,type(a)) print('b =',b) print('c =',c) # fn3(b=1,d=2,c=3,e=10,f=20)
引數解包
# 引數的解包(拆包)
def fn4(a,b,c):
print('a =',a)
print('b =',b)
print('c =',c)
# 建立一個元組
t = (10,20,30)
# 傳遞實參時,也可以在序列型別的引數前新增星號,這樣他會自動將序列中的元素依次作為引數傳遞
# 這裡要求序列中元素的個數必須和形參的個數的一致
# fn4(*t)
# 建立一個字典
d = {'a':100,'b':200,'c':300}
# 通過 **來對一個字典進行解包操作
fn4(**d)
返回值
# 返回值,返回值就是函式執行以後返回的結果
# 可以通過 return 來指定函式的返回值
# 可以之間使用函式的返回值,也可以通過一個變數來接收函式的返回值
def sum(*nums):
# 定義一個變數,來儲存結果
result = 0
# 遍歷元組,並將元組中的數進行累加
for n in nums :
result += n
print(result)
# sum(123,456,789)
# return 後邊跟什麼值,函式就會返回什麼值
# return 後邊可以跟任意的物件,返回值甚至可以是一個函式
def fn():
# return 'Hello'
# return [1,2,3]
# return {'k':'v'}
def fn2() :
print('hello')
return fn2 # 返回值也可以是一個函式
r = fn() # 這個函式的執行結果就是它的返回值
# r()
# print(fn())
# print(r)
# 如果僅僅寫一個return 或者 不寫return,則相當於return None
def fn2() :
a = 10
return
# 在函式中,return後的程式碼都不會執行,return 一旦執行函式自動結束
def fn3():
print('hello')
return
print('abc')
# r = fn3()
# print(r)
def fn4() :
for i in range(5):
if i == 3 :
# break 用來退出當前迴圈
# continue 用來跳過當次迴圈
return # return 用來結束函式
print(i)
print('迴圈執行完畢!')
# fn4()
def sum(*nums):
# 定義一個變數,來儲存結果
result = 0
# 遍歷元組,並將元組中的數進行累加
for n in nums :
result += n
return result
r = sum(123,456,789)
# print(r + 778)
def fn5():
return 10
# fn5 和 fn5()的區別
print(fn5) # fn5是函式物件,列印fn5實際是在列印函式物件 <function fn5 at 0x05771BB8>
print(fn5()) # fn5()是在呼叫函式,列印fn5()實際上是在列印fn5()函式的返回值 10
文件字串
# help()是Python中的內建函式
# 通過help()函式可以查詢python中的函式的用法
# 語法:help(函式物件)
# help(print) # 獲取print()函式的使用說明
# 文件字串(doc str)
# 在定義函式時,可以在函式內部編寫文件字串,文件字串就是函式的說明
# 當我們編寫了文件字串時,就可以通過help()函式來檢視函式的說明
# 文件字串非常簡單,其實直接在函式的第一行寫一個字串就是文件字串
def fn(a:int,b:bool,c:str='hello') -> int:
'''
這是一個文件字串的示例
函式的作用:。。。。。
函式的引數:
a,作用,型別,預設值。。。。
b,作用,型別,預設值。。。。
c,作用,型別,預設值。。。。
'''
return 10
help(fn)
作用域與名稱空間
# 作用域(scope)
# 作用域指的是變數生效的區域
b = 20 # 全域性變數
def fn():
a = 10 # a定義在了函式內部,所以他的作用域就是函式內部,函式外部無法訪問
print('函式內部:','a =',a)
print('函式內部:','b =',b)
# fn()
# print('函式外部:','a =',a)
# print('函式外部:','b =',b)
# 在Python中一共有兩種作用域
# 全域性作用域
# - 全域性作用域在程式執行時建立,在程式執行結束時銷燬
# - 所有函式以外的區域都是全域性作用域
# - 在全域性作用域中定義的變數,都屬於全域性變數,全域性變數可以在程式的任意位置被訪問
#
# 函式作用域
# - 函式作用域在函式呼叫時建立,在呼叫結束時銷燬
# - 函式每呼叫一次就會產生一個新的函式作用域
# - 在函式作用域中定義的變數,都是區域性變數,它只能在函式內部被訪問
#
# 變數的查詢
# - 當我們使用變數時,會優先在當前作用域中尋找該變數,如果有則使用,
# 如果沒有則繼續去上一級作用域中尋找,如果有則使用,
# 如果依然沒有則繼續去上一級作用域中尋找,以此類推
# 直到找到全域性作用域,依然沒有找到,則會丟擲異常
# NameError: name 'a' is not defined
def fn2():
def fn3():
print('fn3中:','a =',a)
fn3()
# fn2()
a = 20
def fn3():
# a = 10 # 在函式中為變數賦值時,預設都是為區域性變數賦值
# 如果希望在函式內部修改全域性變數,則需要使用global關鍵字,來宣告變數
global a # 宣告在函式內部的使用a是全域性變數,此時再去修改a時,就是在修改全域性的a
a = 10 # 修改全域性變數
print('函式內部:','a =',a)
# fn3()
# print('函式外部:','a =',a)
# 名稱空間(namespace)
# 名稱空間指的是變數儲存的位置,每一個變數都需要儲存到指定的名稱空間當中
# 每一個作用域都會有一個它對應的名稱空間
# 全域性名稱空間,用來儲存全域性變數。函式名稱空間用來儲存函式中的變數
# 名稱空間實際上就是一個字典,是一個專門用來儲存變數的字典
# locals()用來獲取當前作用域的名稱空間
# 如果在全域性作用域中呼叫locals()則獲取全域性名稱空間,如果在函式作用域中呼叫locals()則獲取函式名稱空間
# 返回的是一個字典
scope = locals() # 當前名稱空間
print(type(scope))
# print(a)
# print(scope['a'])
# 向scope中新增一個key-value
scope['c'] = 1000 # 向字典中新增key-value就相當於在全域性中建立了一個變數(一般不建議這麼做)
# print(c)
def fn4():
a = 10
# scope = locals() # 在函式內部呼叫locals()會獲取到函式的名稱空間
# scope['b'] = 20 # 可以通過scope來操作函式的名稱空間,但是也是不建議這麼做
# globals() 函式可以用來在任意位置獲取全域性名稱空間
global_scope = globals()
# print(global_scope['a'])
global_scope['a'] = 30
# print(scope)
fn4()