python之動態參數 *args,**kwargs和命名空間

1、函數的動態參數 *args,**kwargs, 形參的順序
一、你的函數,爲了拓展,對於傳入的實參數量應該是不固定,
因此就須要用到萬能參數,動態參數,*args, **kwargspython

1,*args 將全部實參的位置參數聚合到一個元組,並將這個元組賦值給args
(起做用的是* 並非args,可是約定俗成動態接收實參的全部位置參數就用args)app

def sum1(*args):
    print(args)
sum1(1,2,['hello'])             #是一個元組(1, 2, ['hello'])

 

2,**kwargs 將全部實參的關鍵字參數聚合到一個字典,並將這個字典賦值給kwargs
(起做用的是** 並非kwargs,可是約定俗成動態接收實參的全部關鍵字參數就用kwargs)函數

複製代碼
def fun(*args,**kwargs):
    print(args)
    print(kwargs)
fun(1,2,['a','b'],name='xiaobai',age=18)
# 結果:
# (1, 2, ['a', 'b'])       #位置參數,元組
# {'name': 'xiaobai', 'age': 18}       #關鍵字參數,字典
複製代碼

 

二、*的用法
在函數的定義時,*位置參數,**關鍵字參數--->聚合。
在函數的調用(執行)時,*位置參數,**關鍵字參數--->打散。post

實參--->*位置參數--->把位置參數打散成最小的元素,而後一個個添加到args裏組成一個元組this

複製代碼
l1 = [1,2,3]
l2 = [111,22,33,'xiaobai']
#若是要將l1,l2經過函數整合到一塊兒
# 方法一(實參不用*):
def func1(*args):
    return args[0] + args[1]
print(func1(l1,l2))           #[1, 2, 3, 111, 22, 33, 'xiaobai']

# 方法二(實參用*):
def func1(*args):
    return args
print(func1(*l1,*l2))        #(1, 2, 3, 111, 22, 33, 'xiaobai')
複製代碼

 


實參--->**關鍵字參數--->把關鍵字參數打散成最小的元素,而後一個個添加到kwargs裏組成一個字典spa

複製代碼
def func1(**kwargs):
    print(kwargs)

#func1(name='xiaobai',age=18,job=None,hobby='girl')
func1(**{'name':'xiaobai','age':18},**{'job':None,'hobby':'girl'})

# 結果:
# {'name': 'xiaobai', 'age': 18, 'job': None, 'hobby': 'girl'}
複製代碼

 

 

三、形參的順序(a--->b,表明的順序是寫參數時,要先寫a再寫b)
位置參數--->默認參數code

def func(a,b,sex=''):
    print(sex)
func(100,200)

 

位置參數--->*args--->默認參數blog

複製代碼
def func(a,b,*args,sex=''):
    print(a,b)
    print(args)
    print(sex)
func(100,200,1,2,34,5,'',6)
# 結果:
# 100 200               #a,b
# (1, 2, 34, 5,'女',6)  #args
# 男                    #默認參數
複製代碼

 

位置參數--->*args--->默認參數--->**kwargs內存

複製代碼
def func(a,b,*args,sex='',**kwargs):
    print(a,b)
    print(args)
    print(sex)
    print(kwargs)
func(100,200,1,2,34,5,6,sex='',name='xiaobai',age=1000)
func(100,200,1,2,34,5,6,name='xiaobai',age=1000,sex='')
# 兩個的結果都是:
# 100 200              #a,b
# (1, 2, 34, 5, 6)    #args
# 女                  #默認參數修改後的值
# {'name': 'xiaobai', 'age': 1000}     #kwargs

# 如果形參這樣寫:
def func(a,b,*args,**kwargs,sex=''):
    print(a,b)
    print(args)
    print(sex)
    print(kwargs)
func(100,200,1,2,34,5,6,name='xiaobai',age=1000,sex='')
# 結果:會報錯,默認參數必定要寫在kwargs前面
複製代碼

 

 

2、命名空間,臨時命名空間,做用域,取值順序,加載順序等
'''
咱們首先回憶一下Python代碼運行的時候遇到函數是怎麼作的,從Python解釋器開始執行以後,就在內存中開闢裏一個空間,每當遇到一個變量的時候,
就把變量名和值之間對應的關係記錄下來,可是當遇到函數定義的時候,解釋器只是象徵性的函數名讀入內存,表示知道這個函數存在了,至於函數內部的變量和邏輯,解釋器根本不關心。
等執行到函數調用的時候,Python解釋器會再開闢一塊內存來儲存這個函數裏面的內容,這個時候,才關注函數裏面有哪些變量,而函數中的變量會儲存在新開闢出來的內存中,
函數中的變量只能在函數內部使用,由於隨着函數執行完畢,這塊內存中的全部內容也會被清空。作用域

咱們給這個‘存放名字與值的關係’的空間起了一個名字-------命名空間。
代碼在運行開始,建立的存儲「變量名與值的關係」的空間叫作全局命名空間;
在函數的運行中開闢的臨時的空間叫作局部命名空間。
'''


一、python中,命名空間分三種:
  1,全局命名空間
  2,局部命名空間(臨時)
  3,內置命名空間
*內置命名空間中存放了python解釋器爲咱們提供的名字:input,print,str,list,tuple...它們都是咱們熟悉的,拿過來就能夠用的方法。

二、做用域:
  1,全局做用域:全局命名空間 內置命名空間
  2,局部做用域:局部命名空間(臨時)

三、取值順序: 就近原則(LEGB)
局部命名空間 ----> 全局命名空間 ----->內置命名空間          單向 從小到大範圍
也就是說:
  在局部調用時取值順序是:局部命名空間->全局命名空間->內置命名空間
  在全局調用時取值順序是:全局命名空間->內置命名空間


len = 6            #設置全局變量 並且len也在內置命名空間中
def func1():
  len = 3     #設置局部變量
  return len
print(func1())   #返回的len值是局部命名空間的值:3


四、加載順序
內置命名空間(程序運行前加載) ----> 全局命名空間(程序運行中:從上到下加載) --- > 局部命名空間(當函數調用的時候)

 


3、global,nonlocal
一、在局部命名空間 能夠引用全局命名空間的變量,可是不能改變它的值。
count = 1
def func1():
  print(count)
func1()      #引用全局命名空間的變量,結果爲:1


count = 1
def func1():
  count += 1
  print(count)
func1()      #會報錯,由於在局部命名空間中不能直接修改全局命名空間的變量

#若是你在局部名稱空間對一個變量進行修改,那麼解釋器會認爲你的這個變量在局部中已經定義了,
#可是對於上面的例題,局部中沒有定義,因此就會報錯。

二、global:
  1,在局部命名空間聲明一個全局變量。
  2,在局部做用域想要對全局做用域的全局變量進行修改時,須要用到global(限於字符串,數字)。
例子:

複製代碼
def fun():
    global a      #聲明瞭一個全局變量a。
    a = 3
fun()             #調用函數後,就生成了全局變量a,不會由於函數的結束而釋放掉。
print(a)          # 3


count = 1        #全局變量count
def fun():
    global count  #在局部做用域想要對全局做用域的全局變量進行修改時,用global聲明。
    count += 1
fun()
print(count)      # 2
複製代碼

 

ps:對於在全局命名空間可變數據類型(list,dict,set)能夠直接引用並修改不用經過global。

可是函數內部(局部命名空間)可變數據類型在沒有global的聲明下,全局命名空間也是不能夠調用的。

複製代碼
li = [1, 2, 3]  # 全局命名空間的可變數據類型
dic = {'name': 'sb'}


def change():
    li.append('hello')  # 在局部命名空間直接引用並修改
    dic['age'] = 18
change()
print(li)  # [1, 2, 3, 'hello']
print(dic)  # {'name': 'sb', 'age': 18}


def fun():
    l1 = [1, 2, 3]  # 局部名稱空間的可變數據類型

fun()
l1.append(4) 
print(l1)  # 報錯,name 'l1' is not defined


def fun():
    global l1  # 局部名稱空間用global聲明可變數據類型 l1
    l1 = [1, 2, 3]

fun()
l1.append(4)
print(l1)  # [1, 2, 3, 4]
複製代碼

 

三、nonlocal
  1,此變量聲明的變量不能是全局變量,它不能修改全局變量。
  2,子函數對父函數的變量進行修改。(在局部做用域中,對父級做用域(或者更外層做用域非全局做用域)的變量進行引用和修改,而且引用的是哪一層,就從那一層及如下此變量所有發生改變。)
例子:

複製代碼
def func1():
    count = 666
    def inner():
        print(count)
        def func2():
            nonlocal count  #這裏若是不聲明nonlocal,那麼能夠引用父函數的conut值,可是不能修改不然就會報錯
            count += 1
            print('func2',count)
        func2()
        print('inner',count)
    inner()
    print('func1',count)
func1()
# 666 func2 667 inner 667 func1 667
複製代碼

 

 

4、函數的嵌套
一、函數的嵌套定義

複製代碼
def f1():
    print("in f1")
    def f2():
        print("in f2")
    f2()
f1()

#in f1
#in f2


def f1():
    def f2():
        def f3():
            print("in f3")
        print("in f2")
        f3()
    print("in f1")
    f2()
f1()

#in f1
#in f2
#in f3
複製代碼

 

二、函數的嵌套調用

複製代碼
def max1(x,y):
    m = x if x>y else y
    return m

def max2(a,b,c,d):
    res1 = max1(a,b)
    res2 = max1(res1,c)
    res3 = max1(res2,d)
    return res3

print(max2(23,-7,31,11))    # 31
複製代碼
相關文章
相關標籤/搜索