Python3中函數進階

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
"""

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章