1:動態傳參
首先看下下列代碼,實現對2個整數進行求和 運算;如果只有兩個參數的話,函數m_sum是能夠很好地運行,但是如果要對3個,4個甚至更多的整數進行求和運算時,函數m_sum將不能工作。
def m_sum(a,b):
ret = a + b
return ret
print(m_sum(1,3))
那麼要怎樣定義函數才能接收多個個數可變的參數呢,在python中提供了動態傳參,即可以接收任意個參數,代碼如下:
def m_sum(*args):
print(args)
ret = 0
for x in args:
ret += x
return ret
print(m_sum(1,3))
print(m_sum(1,3,4,5))
"""
(1, 3)
4
(1, 3, 4, 5)
13
"""
Python中的動態傳參:
*args 位置參數 接收到的是元組;把位置參數沒有接收的,都被收集到args中;
**kwargs 關鍵字的動態傳參, 接收到的是字典;把關鍵字參數沒有變接收的,都被收集到kwargs中;
"""
形參聲明順序:位置 *args 默認值 **kwargs ;不能是其它順序;
"""
def func( a,b,*args,c = 100,**kwargs ):
print(a, b, c, args,kwargs)
"""
1:調用實參傳遞順序:位置參數,關鍵字參數;(可以全部是關鍵字參數;但不能全部是位置參數)
2:其中位置參數 傳遞給 a,b,*args;a,b被賦值後剩下的以元組的形式給args;
3:關鍵字參數傳遞給 c = 100,**kwargs;匹配默認參數之後,剩下的以字典的形式給kwargs;
4:關鍵字參數之後不能有位置參數傳遞;
5:*args之後的默認值參數必須以關鍵字參數的形式傳遞,不然會永遠都接收不到值,因爲多餘的位置參數會傳遞給args;
"""
# 1,2,3,4,5,6,8 給a,b,*args
# a2 = 20,c = 200 給 c = 100,**kwargs
func(1,2,3,4,5,6,8,a2 = 20,c = 200) # 輸出 1 2 100 (3, 4, 5, 6, 8) {'a2': 20}
# 1, 2, 5, 給a,b,*args
# aa="hello", bb="python", cc="ixusy88" 給 c = 100,**kwargs
func(1, 2, 5, aa="hello", bb="python", cc="ixusy88") # 輸出 1 2 10 (5,) {'aa': 'hello', 'bb': 'python', 'cc': 'ixusy88'}
#下面的調用方式是錯誤的,關鍵詞參數之後不能有位置參數
# func(bb="python",1, b = 2, c=5, aa="hello", cc="ixusy88")
# 全部都是關鍵字參數
func(bb="python",a = 1, b = 2, c=5, aa="hello", cc="ixusy88") # 1 2 5 () {'bb': 'python', 'aa': 'hello', 'cc': 'ixusy88'}
無敵模式. 所有的參數都能接收
def func(*args, **kwargs):
print(args)
print(kwargs)
"*" 和"**" :
在函數定義中:收集參數
在函數調用中:解包參數
# 函數定義的時候:
# *args :收集所有位置參數 ,最終會收集爲一個元祖
# **kwargs:收集所有關鍵字參數,最終會收集爲一個字典
def func(*args, **kwargs):
print(args)
print(kwargs)
func(1,2,3,a=20,b=30)
"""
輸出:
(1, 2, 3)
{'a': 20, 'b': 30}
"""
# 在函數調用的時候:
# * : 會解包參數的集合,它會將序列解包成相應的參數
# ** :會以鍵/值對的形式把一個字典解包爲獨立的關鍵字參數
lst = [1,2,3]
# 作爲一個參數傳遞
func(lst)
"""
輸出:
([1, 2, 3],)
{}
"""
# 把lst中的元素作爲值傳遞
func(*lst) # 與 func(1,2,3) 調用是一樣的
"""
輸出:
(1, 2, 3)
{}
"""
dic = {'name':'ixusy88','age':18}
# 作爲一個參數傳遞
func(dic)
"""
輸出:
({'name': 'ixusy88', 'age': 18},)
{}
"""
# 把dic中的鍵/值對解包爲關鍵字傳遞
func(**dic) # 與 func(name='ixusy88',age=18) 調用是一樣的
"""
輸出:
()
{'name': 'ixusy88', 'age': 18}
"""
2:作用域
Python中有如下作用域:
內置作用域(B):在內置名稱模塊中預先賦值好的名稱(就是在builtins模塊中定義的)。
全局作用域(G):在一個模塊文件頂層被賦值的變量,或者在文件中def 語句內通過global 關鍵字聲明的變量。全局作用域僅限於 單個文件。
外層作用域(E):在外層函數(def或lambda)的局部作用域中的變量,由內向外。
局部作用域(L):在一個函數(def或lambda)中被賦值的變量,不包括那些被global關鍵字聲明的變量。
Python中一個變量的作用域總是由它在代碼中被賦值的位置決定的,而與函數調用無關。
一個變量可以在3個不同的地方被賦值:
a:在def內賦值,它對該函數而言是局部的;
b:在外層的def中賦值,對於內層函數來說,它是非局部的;
c:在所有def外賦值,它對整個文件來說是全局的;
變量名解析規則:LEGB
LEGB :局部作用域(L) ----> 外層作用域(E) ----> 全局作用域(G) ----> 內置作用域(B) ,即對一個變量的引用,會由內到外來查找;
# 全局作用域
a = 100
def func():
# print('1---a=',a) # 此處對a的引用會報錯,因爲a是局部的,引用之前沒有進行賦值操作。
a = 200 # 此處的a爲func的局部作用域,對其賦值,a指向了新的對象,不影響全局作用域中的a
print('2---a=',a)
func()
print('3---a=',a)
"""
2---a= 200
3---a= 100
"""
# global : 在函數局部中聲明變量爲全局的
b = 100
def func():
global b # 在局部作用域中 聲明全局變量b,
print('1---b=',b) # 修改之前
b = 200 # b是全局變量,對其修改就是修改全局作用域中的b
print('2---b=',b)
func()
print('3---a=',b)
"""
1---b= 100
2---b= 200
3---a= 200
"""
3:函數嵌套
在Python中可以對函數進行嵌套,即在函數中也可以定義函數:
# 函數可以互相嵌套
def outer():
def inner():
print("in--inner")
print("in--outer")
inner()
outer()
"""
輸出結果
in--outer
in--inner
"""
# 可以多層嵌套
def outer(cnt):
print(' '*cnt,"outer--開始")
def inner_1(cnt):
print(' '*cnt,"inner_1--開始")
def inner_2(cnt):
print(' '*cnt,"inner_2--")
inner_2(cnt+4)
print(' '*cnt,"inner_1--結束")
inner_1(cnt + 4)
print(' '*cnt,"outer--結束")
outer(0)
"""
輸出結果:
outer--開始
inner_1--開始
inner_2--
inner_1--結束
outer--結束
"""
nonlocal 引入上層局部變量:
# global 引入全局變量, 可以定義全局變量
# nonlocal 引入局部中離他最近的外層變量
a = 100
def outer():
a = 200 # 此處的a爲 outer的局部變量
def inner():
nonlocal a # 找的是局部當中, 離他最近的上層的那個變量,也就是outer中的局部變量。
a = 300 # 修改的是離他最近的上層的那個變量,
print(a) # 300
print(a) # 200,
inner() # 調用內部函數,
print(a) # 300,outer中的局部變量,在inner中被修改。
outer()
print(a) # 100 全部變量
"""
輸出結果:
200
300
300
100
"""
a = 1
def fun_1():
a = 2
def fun_2():
nonlocal a # 引入局部中離他最近的外層變量,及fun_1中的局部變量a
a = 3 # 修改fun_1中的局部變量a的值爲3
def fun_3():
a = 4 # fun_3中的局部變量,對其賦值不影響外部的變量
print('4---',a) # fun_1 中的局部變量a,值在fun_2中被修改爲3,
print('3---',a) # fun_1 中的局部變量a,值在fun_2中被修改爲3,
fun_3() # 此調用沒有修外部的變量
print('5---',a) # fun_1 中的局部變量a,值在fun_2中被修改爲3,
print('2---',a) # fun_1 中的局部變量a,值爲2
fun_2() # 此調用把fun_1 中的局部變量a,修改爲3啦;
print('6---',a) # fun_1 中的局部變量a,值在fun_2中被修改爲3,
print('1---',a) # 全局變量a,值爲1
fun_1()
print('7---',a) # 全局變量a,值爲1
"""
輸出結果:
1--- 1
2--- 2
3--- 3
4--- 4
5--- 3
6--- 3
7--- 1
"""