函數
什么是函數?
函數是可以重復執行的語句塊,可以重復調用並執行函數的面向過程編程的最小單位。
函數的作用:
- 函數用於封裝語句塊,提高代碼的重用性,定義用戶級別的函數、提高代碼的可讀性和易維護性。
函數的語法:
def 函數名(形參列表):
語句塊
作用:創建一個函數,將語句塊打包,用函數名綁定,用來調用
說明:函數名的命名規則與變量名的命名規則相同(必須為標識符),函數名是一個變量,它用來綁定函數。函數有自己的命名空間,函數外部不可以訪問函數內部的變量,函數內部可以訪問函數外部的變量,但不能對外部變量賦值。語句塊部分不能為空,如果為空需要填寫pass語句
函數如果不需要傳入參數,形參列表可以為空。
例子:
#此示例示意用def語句來定義函數
def say_hello():
print('hello world')
print('hello 中國')
函數調用
語法:
函數名(實際調用傳遞參數)
說明:函數調用是一個表達式,如果函數內部沒有return語句,函數執行完畢后返回None對象的引用
例子:
def say_hello():
print("hello world")
print("hello 中國")
#函數調用第一次
say_hello()
#函數調用第二次
say_hello()
#此示例示意用def語句定義函數
#函數外部的變量訪問不了函數內部的變量
def say_hello():
a = 100
print("內部a是:",a)
say_hello()
#定義一個有參數的myadd函數
def myadd(a,b):
print(a+b)
myadd(1,2)
myadd([1,2,3],[4,5,6])
return語句
語法:
return [表達式]
注釋:[]代表其中的內容可以省略
作用:用於函數中,結束當前函數的執行,返回到調用該函數的地方,同時返回一個對象的引用關系
說明:
- return語句后面的表達式可以省略,省略后相當於return None
- 函數內部沒有return語句的,則該函數執行完最后一條語句后返回None
練習:
1.寫一個函數mymax,實現返回三個最大的值
如:def mymax(a,b,c):
……….
print(mymax(1,2,3))#3
print(mymax(“ABC”,“abc”,“123”))#abc
#小白寫法
def mymax(a,b,c):
return max(a,b,c)
print(mymax(1,2,3))
print(mymax("ABC","abc","123"))
#經典寫法
def mymax(a,b,c):
zuida = a
if b > zuida:
zuida = b
if c > zuida:
zuida = c
return zuida
print(mymax(1,2,3))
print(mymax("ABC","abc","123"))
函數的傳參
作用:把數據給函數
函數的形參
作用:接收函數調用傳過來的數據
python函數的參數傳遞
傳遞方式:
- 位置傳參
- 序列傳參
- 關鍵字傳參
- 字典關鍵字傳參
位置傳參
實際參數(實參)的對應關系與形式參數(形參)的對應關系是按照位置來依次對應的
示例:
# 此示例示意位置傳參
def myfun(a, b, c):
'''這是一個函數傳參的示例'''
print('a的值是:', a)
print('b的值是:', b)
print('c的值是:', c)
myfun(1, 2, 3)
myfun(4, 5, 6)
myfun("ABC", [1,2,3], (44,55,66))
說明:
實參和形參通過位置進行傳遞和匹配
實參的個數必須與形參的個數相同
序列傳參
序列傳參是指在函數調用過程中,用*(星號)將序列拆解后
按照位置進行傳遞的傳參方式
示例:
# 此示例示意 序列傳參
def myfun(a, b, c):
'''這是一個函數傳參的示例'''
print('a的值是:', a)
print('b的值是:', b)
print('c的值是:', c)
L = [11, 22, 33]
# myfun(L[0], L[1], L[2])
myfun(*L)
# myfun(L)
說明:
序列傳參時,序列拆解的位置將與形參一一對應
關鍵字傳參
關鍵字傳參是指傳參時,按照形參名稱給形參賦值
實參和形參按名稱進行匹配
示例:
# 此示例示意 關鍵字傳參
def myfun(a, b, c):
'''這是一個函數傳參的示例'''
print('a的值是:', a)
print('b的值是:', b)
print('c的值是:', c)
myfun(c=33, b=22, a=11)
myfun(b=222, c=333, a=111)
說明:
可以不按照位置進行匹配
傳參的順序可以寫亂
字典關鍵字傳參
字典關鍵字傳參是指實參為字典,將字典用**(雙星號)拆解后進行關鍵字傳參的傳遞方式
示例:
# 此示例示意 字典關鍵字傳參
def myfun(a, b, c):
'''這是一個函數傳參的示例'''
print('a的值是:', a)
print('b的值是:', b)
print('c的值是:', c)
d = {'a':100, 'c':300, 'b':200}
# myfun(a=d['a'], c=d['c'], b=d['b'])
myfun(**d) # 等同於上面一條語句
# myfun(d) # 出錯
說明:
字典的鍵名和形參名必須一致
字典的鍵名必須符合標識符命名規則的字符串
字典的鍵名要在形參中存在
函數的綜合傳參
函數的傳參方式在能確定形參能唯一匹配到相應實參的情況下可以任意組合
函數的位置傳參要優先於關鍵字傳參
示例:
def myfun(a, b, c):
pass
myfun(100, *[200, 300])
myfun(100, *"BC")
myfun(*"AB", 300)
myfun(*[100], 200, *[300])
myfun(100, c=300,b=200)
myfun(a=100, 200, c=300) # 錯誤的
myfun(100, **{'c':300, 'b':200})
myfun(100, **{'c':300}, b=200)
myfun(100, b=200, **{'c':300})
函數的缺省參數
語法:
def 函數名(形參名1=默認實參1,形參名2=默認實參2,形參名3=默認實參3,.....)
作用:
讓函數的調用者少傳遞參數來調用函數
示例:
# 此示例示意如何定義函數的缺省參數
def info(name, age=1, address="不詳"):
print(name, '今年', age,'歲,家庭住址:',
address)
info("魏明擇", 35, "北京市朝陽區")
info("Tarena", 15)
info("張飛")
# info() # 出錯
說明:
缺省參數必須自右至左一次存在,如果一個參數有缺省參數,則其右側的所有參數必須有缺省參數
缺省參數可以有0個、一個或多個,甚至全部都有缺省參數
例子:
def fn(a,b=10,c): #錯誤
pass
def fn(a=0,b=None,c=False): #正確
pass
函數的可變實參和不可變實參的傳遞
示例:
# 在函數內部對變量賦值是在函數內部創建新的局部變量
# 此賦值語句不會改變外部變量的綁定關系
L = [1, 2, 3]
def f1(L):
L = [4, 5, 6] # 賦值語句的作用是創建和或改變變量的綁定關系
print(L) # [4, 5, 6]
f1(L)
print(L) # [1, 2, 3]
L = [1, 2, 3]
def f1(L):
# L = [4, 5, 6] # 賦值語句的作用是創建和或改變變量的綁定關系
L.append("ABC")
print(L) # [1, 2, 3, "ABC"]
f1(L)
print(L) # [1, 2, 3, "ABC"]
說明:
當一個可變通過函數實參傳入函數內時,在函數內可以通過局部變量來操作可變對象(列表,字典,集合...)
面試題:
#運行以下程序的結果是什么?為什么?
L = [1,2]
def fn(a,lst=[])
lst.append(a)
print(lst)
fn(3,L) #[1,2,3]
fn(4,L) #[1,2,3,4]
#####################
fn(5) #[5]
fn(6) #[5,6]
fn(7) #[5,6,7]
函數形參的定義方式
- 位置形參
- 星號元組形參
- 命名關鍵字形參
- 雙星號字典形參
位置形參
語法:
def 函數名(形參變量1,形參變量2,....):
語句塊
星號元組形參
語法:
def 函數名(*元組形參名):
語句塊
作用:
收集多余的位置傳參
說明:
元組形參名一般命名為'args'
*元組形參一個函數只能有一個
示例:
# 此示例示意星號元組形參
def func(*args):
print("實參的個數是:", len(args))
print("args=", args)
func() # 無參
func(1,2,3,4)
func(1, 2, 3, 4, 5, 6, 7, 8)
s = "ABCDE"
func(*s) # 等同於func('A', 'B', ....)
func(a=100, b=200) # 出錯
命名關鍵字形參
語法:
def 函數名(*,命名關鍵字形參1,命名關鍵字形參2,....):
語句塊
或
def 函數名(*args,命名關鍵字形參1,命名關鍵字形參2,....):
語句塊
作用:
強制所有的命名關鍵字形參都必須用關鍵字傳參或字典關鍵字傳參
示例:
# 此示例示意命名關鍵字形參
def func(a, b, *, c, d):
print(a, b, c, d)
# func(1, 2, 3, 4) # 傳參失敗
func(1, 2, c=30, d=40)
func(a=10, b=20, c=30, d=40)
func(1, 2, **{'d':400, 'c':300})
雙星號字典形參
語法:
def 函數名(**字典形參名):
語句塊
作用:
收集多余的關鍵字傳參
示例:
# 此示例示意雙星號字典形參
def func(**kwargs):
print("關鍵字傳參的個數是:", len(kwargs))
print('kwargs=', kwargs)
func(name="隔壁老王", age=35, address="朝陽區")
def func(*,a, b, **kwargs):
print("關鍵字傳參的個數是:", len(kwargs))
print('kwargs=', kwargs)
func(a=1, b=2, c=3, d=4)
說明:
字典形參名一般命名為:'kwargs'
一個函數內字典形參最多只有一個
函數的形參說明:
- 位置形參,缺省參數,星號元組形參,雙星號字典形參可以混合使用
- 函數形參自左至右的定義順序為:
- 位置形參
- 星號元組形參
- 命名關鍵字形參
- 雙星號字典形參
示例:
def fn(a, b, *args, c, **kwargs):
pass
fn(1, 2, 3, 4, c=30, d=40, e=50)
函數的不定長參數
- 星號元組形參
- 雙星號字典形參
用不定長參數可以接收任意的傳參
如:
def fn(*args,**kwargs):
print(*args,**kwargs)
全局變量和局部變量
局部變量
- 定義在函數內部的變量稱為局部變量(函數的形參也是局部變量)
- 局部變量只能在函數內部使用
- 局部變量在函數調用時才能創建,在函數調用之后會自動銷毀
全局變量
- 定義在函數外部的變量稱為全局變量
- 全局變量所有的函數都可以直接訪問(但函數內部不能將其直接復制)
說明:
函數內部復制語句不會對全局變量造成影響
函數變量
函數名是變量,它在創建函數時綁定一個函數
示例:
# 此示例示意函數名為變量,可以其它變量來綁定同一個函數
def f1():
print("f1函數被調用!")
f2 = f1 # 看清楚,不是 f2 = f1() <<===沒括號
f2() # 調用哪兒個函數?
f1()
def f1():
print("f1函數被調用!")
def f2():
print("f2函數被調用!")
f1, f2 = f2, f1 # 交換兩個函數名變量的綁定關系
f1() # 請問調用誰?
說明:
一個函數可以作用另一個函數的實參傳遞
可以把一個函數給另一個函數,另一個函數的形參變量將
綁定實參函數
函數可以作為另一個函數的返回值
示例:
def f1():
print("f1")
def f2():
print("f2")
def get_fx(n):
if n == 1:
return f1
elif n == 2:
return f2
fx = get_fx(1)
fx() # 調用f1
fx = get_fx(2)
fx() # 請問調用誰?
函數的嵌套定義
函數嵌套定義是指一個函數里用def 語句來創建其他函數的情況
示例:
# 此示例示意在函數內部創建函數,在函數內部來調用
def fn_outer():
print("fn_outer被調用")
def fn_inner():
print("fn_inner被調用")
fn_inner()
fn_inner()
fn_inner()
print("fn_outer調用結束")
fn_outer()
# fn_inner() # 調用出錯