函數一詞來源於數學,編程中的"函數"與數學中的函數有很大的不一樣。
(BASIC中叫subroutine,C中叫function,java中叫method)
java
定義:函數是指將一組語句的集合經過一個名字(函數名)封裝起來,想執行這個函數,只需調用其函數名便可。 python
(1)減小重複代碼:不然遇到重複的功能只能重複編寫實現代碼,代碼冗餘linux
(2)使程序變得可擴展:不然功能須要擴展時,須要找出全部實現該功能的地方修改之,沒法統一管理且維護難度極大 c++
(3)使得程序變得易維護:不然代碼的組織結構不清晰,可讀性差編程
(1)內置函數:針對一些簡單的功能,python解釋器已經爲咱們定義好了的函數即內置函數。對於內置函數,咱們能夠拿來就用而無需事先定義,如len(),sum(),max()。數組
(2)自定義函數:很明顯內置函數所能提供的功能是有限的,這就須要咱們本身根據需求,事先定製好咱們本身的函數來實現某種功能,之後,在遇到應用場景時,調用自定義的函數便可運維
參數的做用:可讓函數更靈活,不僅能作死動做,還能夠根據調用時傳參的不一樣來決定函數內部的執行流程。函數
# 無參函數 def sayhi(): # 函數名(小寫便可) print("Hello,I'm nobody!") sayhi() # 調用函數,函數名指向上述代碼指向的內存位置,加上括號纔是執行代碼 print(sayhi) # 函數sayhi指向的內存地址 # 單個參數的函數 def sayhi(name): print("hello",name) print("my name is black girl....", name) sayhi("tracy") # 多個參數函數 def calc(x,y): # 定義算數函數 res = x**y return res # 返回函數執行結果 a,b = 5,8 c = calc(a,b) # 結果賦值給變量c print(c) calc(2,10) # 直接寫入參數
只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。所以,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量測試
能夠是常量、變量、表達式、函數等,不管實參是何種類型的量,在進行函數調用時,它們必須有肯定的值,以便把這些值傳送給形參。所以應預先用賦值,輸入等辦法使參數得到肯定值spa
def calc(x,y): # 形參 res = x**y return res a,b = 3,5 c = calc(a,b) # 實參 print(c) d = calc(2,3) # 實參
def stu_register(name,age,country,course): print("註冊學生信息".center(50,'-')) print("姓名:",name) print("age:" ,age) print("國籍",country) print("課程",course) stu_register("山炮",22,"CN","python_devops") stu_register("豐收",23,"CN","linux") ''' 因爲不少人國籍都是中國,能夠將country設置爲默認參數 默認參數: ''' def stu_register(name,age,course,country="CN"): # 非默認參數不能跟在默認參數後面 print("registration info".center(50,'-')) print(name,age,country,course) stu_register("jack",22,'c++') # 實參和形參按順序一一對應 stu_register("rain",32,'dance','Korean') stu_register("Alfa",21,'python')
應用場景:正常狀況下,給函數傳參數要按順序,不想按順序能夠用關鍵參數
定義:指定了參數名的參數就叫關鍵參數
關鍵參數必須放在位置參數(以位置順序肯定對應關係的參數)以後
def stu_register(name,age,course,country='CN'): print("註冊學生信息".center(50,'-')) print("姓名:",name) print("age:" ,age) print("國籍",country) print("課程",course) stu_register("綺珊",course='Python',age=22,country='JP') # 後三個均爲爲關鍵參數置於name位置參數以後 # stu_register("杉樹",course='Python',22,country='JP') # 22爲位置參數不能放在關鍵參數course以後 # stu_register("曼玉",22,age=25,country='JP') # age得到多個賦
形式參數中出現*,傳遞的參數就能夠再也不是固定個數,會將傳過來的全部參數打包爲元組。
def send_alert(msg,*users): for u in users: print('報警發送給',u) # 方式一: # 報警,十個運維人員 send_alert('注意系統資源別浪了','Alex','jack','tracy','wood') # 方式二: # send_alert('注意內存緊張',['alex','jack','tracy','wood']) # 傳入的參數是數據 send_alert('注意內存緊張',*['alex','jack','tracy','wood']) # 傳入的參數是數組內的元素 # 傳入的參數由(['alex','jack','tracy','wood']) ————>('alex','jack','tracy','wood')
若是動態參數後還有參數
# 方法一: def send_redalert(msg,*users,age): for u in users: print('CPU緊張',u) # send_redalert("alex","rain",22) # 22也會傳遞給*users send_redalert("alex","rain",age=22) # 方法二: def func(name,*args,**kwargs): print(name,args,kwargs) func('Alex',22,'tesla','500w',addr='湖北',num=123332313) # Alex (22, 'tesla', '500w') {'addr': '湖北', 'num': 123332313} d = {'degree':'primary school'} func('Peiqi',**d)
優勢:使用*args和**kwargs能夠很是方便的定義函數,同時能夠增強擴展性,以便往後的代碼維護。
返回值:函數外部的代碼要想獲取函數的執行結果,能夠在函數裏用return語句把結果返回。
注意:
一、函數在執行過程當中只要遇到return語句,就會中止執行並返回結果,能夠理解return語句表明着函數的結束
二、若是未在函數中指定return,那這個函數的返回值爲None
def stu_register(name,age,course='PY',country='CN'): print("註冊學生信息".center(50,'-')) print("姓名:", name) print("age:", age) print("國籍", country) print("課程", course) if age > 22: return False else: return True registration_status = stu_register('阿斯頓',22,course="全棧開發",country='JP') if registration_status: print("註冊成功".center(50,'-')) else: print("too old to be a student.") ''' 執行到return語句後,中止執行函數並返回結果 ''' def stu_register(name,age,course): print(name,age,course) # # if age > 22: # return 'sdfsf' # 返回值能夠是任意值 # else: # return True # # return None # 到return語句後,中止執行函數並返回結果 # print('hahah') # return 1 return [name,age] status = stu_register('Peiqi',29,'安保') print(status)
局部變量:函數內定義的變量,只能在局部生效
全局變量:定義在函數外部一級代碼的變量,整個程序可用(由上到下可用)
在函數內部能夠引用全局變量。
變量查找順序:若是全局和局部都有一個變量,函數查找變量的順序是由內而外的。兩個函數間互不可見
name = "Black girl" # 全局變量 def change_name(): # global name # (不建議使用global)在函數內修改全局變量,不能放在函數內局部變量後面 name = "黑色的姑娘" # 局部變量 print("在",name,"裏面...",id(name)) change_name() print(name,id(name)) # 與函數內的變量內容徹底不一樣 ''' 輸出結果: 在 黑色的姑娘 裏面... 4302993904 Black girl 4316351984 '''
函數內能夠修改字典、列表、集合、對象、類、元組內的列表
names = ['Alex','Black Girl','Peiqi'] def change_name(): names = ['Alex'] del names[2] # names總體的內存地址不能修改只能引用,但其內部的元素是能夠修改的 names[1] = "黑姑娘" print(names) change_name() print(names) ''' 輸出結果: ['Alex', '黑姑娘'] ['Alex', '黑姑娘'] '''
做用域定義:一段程序代碼中所用到的名字並不老是有效/可用的,而限定這個名字的可用性的代碼範圍就是這個名字的做用域。
age = 18 def func1(): age = 73 def func2(): age = 84 print(age) return 666 val = func1() print(val) ''' 輸出:666 '''
# 函數名能夠看成返回值 age = 18 def func1(): age = 73 def func2():... return func2 # 返回一個函數名# val = func1() print(val) ''' 輸出:<function func1.<locals>.func2 at 0x101462598> ''' # 代碼寫完以後做用域已經生成,無論函數名傳到哪裏,只要執行都回回定義的地方往上找 age = 18 def func1(): age = 73 def func2(): print(age) return func2 # 返回一個函數名不帶括號 val = func1() val() ''' 輸出結果:73 '''
嵌套函數,就是指在某些狀況下,您可能須要將某函數做爲另外一函數的參數使用。
def func1(): print('alex') def func2(): print('eric') func1() ''' 輸出:alex ''' def func1(): print('alex') def func2(): print('eric') func2() func1() ''' 輸出: alex eric '''
總結:
函數內部能夠再次定義函數
執行函數須要被調用
age = 19 def func1(): age = 73 print(age) # 尋找變量,先找本身的函數內,沒有就找全局變量(一層一層往上找) def func2(): age = 84 print(age) # 尋找變量,優先本身函數、再找父級、爺爺級,最後找全局變量 func2() func1() # 輸出:73 84
# 測試二: age1 = 19 def func1(): age1 = 73 def func2(): print(age1) # 按順序往上找,找到父級的age=73 func2() func1() # 輸出:73
age = 19 def func1(): def func2(): print(age) age = 73 func2() func1() """ 輸出: 73 """ age = 19 def func1(): def func2(): print(age) func2() age = 73 func1() ''' 執行報錯:free variable 'age' referenced before assignment in enclosing scope 73在func2後面,func2不知道該取哪一個參數 '''
爲了不這種狀況,聲明變量儘可能寫在前面。
age = 19 def func1(): global age # 此時已經拿到age=19,age=73尚未執行 def func2(): print(age) func2() age = 73 # 此時修改全局age=73 func1() print(age) """ 輸出: 19 73 """ age = 19 def func1(): global age def func2(): print(age) age = 73 # 將全局變量age改成73,再執行func2,函數沒有在func2\func1中找到age,繼續到全局找age,但全局已經修改成73 func2() func1() print(age) """ 輸出: 73 73 """
第一個程序,在global age時,函數已經拿到age=19,但此時age=73尚未執行,此時執行func2函數,打印age=19。隨後修改全局變量age=73,直接打印age,所以輸出73.
第二個程序,在global age時,函數拿到age=19,隨後修改全局變量age=73,接着執行func2函數,打印age=73,打印此時的全局變量age,也一樣輸出73.