Cris 的Python筆記(六):函式基礎
阿新 • • 發佈:2018-12-17
1. 函式基礎語法知識
# 函式:函式也是一個物件,用來儲存可執行的程式碼並且在需要時隨時呼叫;而物件就是記憶體中用來儲存資料的一片記憶體空間
# 建立函式:def 函式名([arg1,arg2...]):
# 程式碼塊
def func():
print('hello,cris')
print('i am function of python')
# 呼叫函式
func()
print(type(func)) # <class 'function'>
# 函式的形參:定義形參相當於在函式內部定義了變數,但是並沒有賦值
# 函式的實參:如果函式定義了實參,那麼呼叫該函式時就需要傳遞對應的實參
def func(a, b):
return a + b
result = func(1, 2)
print(result) # 3
# 函式引數詳解:1. 可以為函式的形參指定預設值,如果使用者傳遞了引數,則預設值失效;如果使用者沒有傳遞實參,那麼預設值生效
# 2.實參的傳遞方式:位置;關鍵字
def func(a, b, c=10):
print(a, b, c)
# 位置傳參
func(1, 2, 3) # 1 2 3
# 關鍵字傳參
func(c=11, a=12, b=0) # 12 0 11
# 位置傳參和關鍵字傳參可以混合使用,但是位置引數必須寫在關鍵字引數前面,否則無法區分
# func(b=12,23,11) # 報錯
# 函式呼叫時,無法對實參進行型別檢查(Python 是一種動態語言);所以實參可以傳遞任意資料型別
func(func, 22) # <function func at 0x000001836D1057B8> 22 10
# Python 中的值傳遞:實參如果指向的是可變資料型別的物件,那麼函式中形參修改物件將會影響到所有指向這個物件的變數;
# 實參如果指向的是不可變資料型別,那麼形參的修改將不會對實參產生任何影響(換句話說,Python和java 類似,引數傳遞都是值傳遞型別)
def func(a):
a = 'cris'
print(a)
b = 'james'
func(b)
print(b)
# 不定長函式:定義引數時,可以在一個形參前面加上*,這個形參就會獲取到所有的實參,並且以元祖的形式展現,也稱之為引數的裝包
# 帶* 號的引數只能寫一個,並且可以和其他形參聯合使用:例如(a,b,*c)
# 如果帶* 號的形參寫在中間,那麼帶* 號的形參後面的所有引數都必須以關鍵字的形式傳遞引數
# 如果在形參列表的開頭寫一個*,那麼表示該函式的實參都必須以關鍵字的形式來傳參:(*,a,b,c)
def sum(a, *b):
print(a, b, type(b))
sum(1, 2, 3) # 1 (2, 3) <class 'tuple'>
def sum(*nums):
result = 0
for i in nums:
result += i
print(result)
sum(1, 2, 3, 4) # 10
# *號形參只能接受位置引數
def func(*a):
print(a)
func(1, 2, 3) # (1, 2, 3)
# func(b=2, c=3) # 報錯
# 如果使用**號形參可以接受任意個關鍵字傳參,預設會將這些引數統一儲存到字典中,字典的key 就是引數的名字,value就是引數的值。**號形參只能寫一個,並且必須寫在最後一個
def func(**a):
print(a)
func(b=1, c=2) # {'b': 1, 'c': 2}
# 引數的解包:傳遞實參時,可以在序列型別的引數前面加上*,這樣就會自動將序列中的元素依次作為引數傳遞
def func(a, b, c):
print(a, b, c)
args = (1, 2, 3)
func(*args) # 1 2 3
# 兩個** 可以對字典解包,前提是引數名和key名需要一一對應
args = {'a': 100, 'b': 200, 'c': 300}
func(**args) # 100 200 300
# 函式的返回值: return 關鍵字可以返回任意資料型別的物件(甚至函式),可以直接使用函式的返回值,或者使用變數來接收;
# return後面不加值或者不寫return,則相當於return None;return 還可以用於結束函式
# break,continue,return 之間的區別
# fn 和 fn()的區別:一個是函式物件,一個是呼叫函式的結果
def sum(*nums):
result = 0
for i in nums:
result += i
return result
result = sum(1, 2, 3)
print(result) # 6
# return 後面接函式物件的特殊情況(JAVA 無法這樣)
def fn1():
def fn2():
print('this is fn2')
return fn2
f = fn1()
f() # this is fn2
2. 文件字串(Python中的函式規範)
# 文件字串:doc string,用於定義函式的說明
# help()是Python的內建函式,可以用於查詢Python中函式的用法(但是可以使用外掛自動提示~)
# help(print)
# 直接在函式的第一行使用```xxx```來書寫函式說明
# 如果要寫的更加規範和講究,可以參考下面的Python 寫法:
# 1. 在每個引數的後面使用:資料型別 來為函式的形參做出型別要求(但是無法進行強制檢查,僅僅提示)
# 2. 然後在函式宣告的末尾使用 -> 資料型別 來對該函式的返回值做出型別提示
def func1(a: int, b: bool, c: str='cris') -> str:
'''
函式的作用:
引數a:
引數b:
引數c:
返回值:
'''
print(a, b, c) # 1 True cris
return str(a) + str(b) + c
help(func1) # 檢視函式的說明
print(func1(1, True)) # 1Truecris
3. 函式的作用域和名稱空間
# 函式變數的作用域(scope):在Python 中,變數一共有兩種作用域:一種是全域性作用域;一種是函式作用域
# 全域性作用域:
# - 在程式執行的時候建立,程式執行結束後銷燬
# - 所有函式以外的區域都是全域性作用域
# - 在全域性作用域中定義的變數,都屬於全域性變數,全域性變數可以在程式的任意位置被訪問
# 函式作用域:
# - 函式作用域在函式被呼叫時建立,呼叫結束後被銷燬
# - 函式沒呼叫一次,就會建立一個新的函式作用域
# - 在函式作用域中定義的變數,就是區域性變數,只能在函式內部被訪問
a = 10
def fn():
print(a)
fn() # 10
# 作用域支援就近原則以及層級巢狀(由內往外)
def fn1():
a = 11
def fn2():
a = 12
print("a:", a)
fn2()
fn1() # a:12
# 如果想要在函式內部修改全域性作用域的變數,需要使用 global 關鍵字
def fn3():
# 宣告全域性作用域的變數
global a
a = 'cris' # 對全域性作用域的變數進行修改
print('cris=', a)
fn3() # cris= cris
print('a=', a) # a= cris
# 命令空間(namespace):命令空間指的就是變數儲存的位置,每一個變數都需要儲存到對應的名稱空間中去
# 即每一個作用域都有其對應的名稱空間:全域性作用域對應的全域性名稱空間用來儲存全域性變數;函式作用域對應的區域性名稱空間用來儲存區域性變數
# 名稱空間實質上就是一個字典,宣告的變數都是以key-value 的形式儲存到這個字典中
# locals()函式用於獲取名稱空間,在全域性作用域呼叫獲取的是全域性名稱空間;在函式作用域呼叫,獲取的是函式的名稱空間
space = locals()
print(type(space)) # <class 'dict'>
print(space['a']) # cris
# 宣告變數其實就是在往名稱空間新增鍵值對
space['b'] = 123
# print(b) # 123,不推薦使用這種方式定義變數,瞭解即可
# 可以通過global()在任意位置獲取全域性名稱空間,不建議使用