目錄:python
1.三元運算web
2.定義函數數組
3.函數參數詳解閉包
4.函數嵌套app
5.函數命名空間函數
6.函數名的靈活應用url
7.閉包spa
1 a = 1
2 b = 2
3 if a < b : 4 c = b 5 else: 6 c = a
這樣寫代碼很是繁瑣,因此在遇到if else很是簡單的時候,能夠用到三元運算code
a = 1 b = 2 c = b if a < b else a
①---⑥表示寫三元運算時候的流程
二.函數:
函數是組織好的,可重複使用的,用來實現單一,或相關聯功能的代碼段。
函數能提升應用的模塊性,和代碼的重複利用率。你已經知道Python提供了許多內建函數,好比print()。
但你也能夠本身建立函數,這被叫作用戶自定義函數。
函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()。
任何傳入參數和自變量必須放在圓括號中間,圓括號之間能夠用於定義參數。
函數的第一行語句能夠選擇性地使用文檔字符串—用於存放函數說明。
函數內容以冒號起始,而且縮進。
return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return至關於返回 None
函數定義示例:
1 def 函數名(參數1,參數2): 2 '''
3 這是一個解決什麼問題的函數 4 :param 參數1: 參數1表明輸入什麼 5 :param 參數2: 參數2表明輸入什麼 6 :return: 返回什麼東西 7 '''
8 函數體 9 返回值 10 return 返回值
例如定義計算字符串長度的函數:
1 def my_len(my_str): #定義函數
2 '''
3 用於計算可變類型長度的函數 4 :param my_str: 用戶輸入的參數內容 5 :return:返回參數的長度 6 '''
7 count = 0 8 for val in my_str: 9 count += 1
10 return count 11 a = my_len("hightgood") 12 print(a) #輸出值9
定義一個函數後,儘可能不要用print,儘可能return結果
本身是能夠知道函數代碼內部打印的是啥,本身能夠隨時修改,可是別人不知道
函數中的return:
1.返回None
有三種狀況:
(1)無return的狀況
(2)原本就return None
(3)return #return空白
#無return
def my_print(parameter): print("Welcome",parameter) #return None
def my_print(parameter): return None #return
def my_print(parameter): return #通常用於結束函數體
2.返回一個值
1 def my_len(my_str): #定義函數
2 #計算可變類型值的長度
3 my_str = "goodnight"
4 count = 0 5 for val in my_str: 6 count += 1
7 return count #count就是那個返回值
3.返回多個值
1 def my_print(): 2 return 11,22,33,[1,2,3] 3 a = my_print() 4 print(a) 5 #打印結果:(11, 22, 33, [1, 2, 3])
return後面的值用逗號隔開,而後以元組的形式返回
4.結束函數代碼
1 def my_print(): 2 print('one') 3 return #遇到return不繼續函數下面的代碼
4 print('two') 5 my_print() #結果:one
5.補充:接收多個值
1 def my_print(): 2 return 1,2,3
3 a,b,c=my_print() 4 print(a,b,c) #至關於用a接收1,b接收2,c接收3
5 def my_print(): 6 return [4,5,6] 7 a,b,c=my_print() 8 print(a,b,c) #一個列表裏有三個值,分別用abc去接收,至關於解包
1 def my_len(my_str): #這裏的my_str就是形參,形式參數,輸入對象不肯定,形參能夠有多個,用逗號隔開
2 my_str = "goodnight"
3 count = 0 4 for val in my_str: 5 count += 1
6 return count 7 a = my_len("hightgood") #這裏的hightgood就是實參,實際參數,輸入對象肯定
8 print(a)
函數參數詳解:
1.位置參數:
1 def demo_1(a,b): #位置參數 用戶必須傳入的參數,不傳會報錯
2 print(a,b) 3 demo_1(1,2) #輸出結果:1 2 按照位置傳參
4 demo_1(b=1,a=2) #輸出結果:2 1 按照關鍵字傳參
5 demo_1(1,b=2) #輸出結果:1 2 混用,但必須注意先按照位置傳參,再按照關鍵字傳參,否則會報錯
2.默認參數:
1 def welcome(name,sex='man'): #sex爲默認參數
2 print('welcome %s,sex %s'%(name,sex)) 3 welcome('zrh') #輸出結果:welcome zrh,sex man
4 welcome('lml','women') #輸出結果:welcome lml,sex women
5 #默認參數若是不傳參數,就用默認值,若是默認參數傳入參數,就用傳入值
默認參數的陷阱:
(1)
1 a = 18
2 def age(a1,a2=a): 3 print(a1,a2) 4 a = 20
5 age(10) #輸出結果:10 18
內部原理:
(2)
專門針對可變數據類型
1 def demo(a = []): 2 a.append(1) 3 print(a) 4 demo() #輸出結果:[1]
5 demo() #輸出結果:[1] [1]
6 demo() #輸出結果:[1] [1] [1]
7 def demo_1(a = []): 8 a.append(1) 9 print(a) 10 demo_1([]) #輸出結果:[1]
11 demo_1([]) #輸出結果:[1]
12 demo_1([]) #輸出結果:[1]
由於可變類型改變不是在內存中開闢一個新空間,而是在原來的基礎上作修改,而10--12行是開闢了三塊新內存
3.動態參數:
定義動態參數
1 def demo(*agrs): #按位置輸入的動態參數,組成一個元組
2 pass
3 def demo_1(**kwargs): #按關鍵字傳入的參數,組成一個字典
4 pass
站在函數定義的角度:*作聚合做用,將一個一個的參數組合成一個元組(**則是字典)
站在函數調用的角度:*作打散用,將一個列表或元組打散成多個參數(**則是關鍵字形式)
1 #函數定義角度:
2 def demo(*agrs): #按位置輸入的動態參數
3 print(agrs) 4 demo(1,2,3,4,5) #輸出結果(1, 2, 3, 4, 5)
5 def demo_1(**kwargs): #按關鍵字傳入的參數,組成一個字典
6 print(kwargs) 7 demo_1(a=1,b=2,c=3) #輸出結果{'a': 1, 'b': 2, 'c': 3}
8 #函數調用角度:
9 val = [1,2,3,4] 10 val2 = {'a':1,'b':2} 11 demo(*val) #將val打散成 1 2 3 4,而後傳入函數
12 demo_1(**val2) #將val2打散成 a=1 b=2,而後傳入函數
解釋一下爲何在混用的傳參中有必須先按位置傳參,再按關鍵數傳參:
1 def demo(*agrs,**kwargs): #*agrs和**kwargs的位置是python固定死的
2 #因此必須先是按照位置傳參的*agrs,再是按照關鍵字傳參的**keagrs
3 print(agrs) 4 print(kwargs) 5 demo(1,2,3,4,a = 1,b = 2) 6 # 輸出結果:
7 # (1, 2, 3, 4)
8 # {'a': 1, 'b': 2}
第3行對應第7行的輸出結果
第4行對應第8行的輸出結果
定義多個不一樣類型參數時的順序:
1 def demo(位置參數1,位置參數2,*args,默認參數=x,**kwargs): 2 pass
3 #之後職業生涯用到多種參數時必須這麼寫
格式及原理:
狀況總結:
1 def demo(*args,**kwargs): #接收參數個數不肯定的時候用動態傳參,用到的時候再用
2 pass
3 def demo_1(a,b,c): #位置參數,幾個參數必須都要傳入幾個值,最經常使用
4 pass
5 def demo_2(a,b=10): #默認參數,當參數信息大量形同時用到
6 pass
函數案例:
需求:寫函數,用戶輸入操做文件名字,將要修改的內容,修改後的內容,而後進行批量操做
1 def dict_change(filename,old_content,new_content): 2 '''
3 函數用於文件內容批量修改操做 4 :param filename: 操做對象的名字 5 :param old_content: 將要修改的值 6 :param new_content: 修改後的值 7 :return:無返回值 8 '''
9 import os 10 with open(filename,encoding='utf-8') as file_old,open('new_file','w',encoding='utf-8') as file_new : 11 for val_old in file_old: 12 val_new = val_old.replace(old_content,new_content) 13 file_new.write(val_new) 14 os.remove(filename) 15 os.rename('new_file',filename) 16 dict_change('file','.','=')
修改後的文件:
1 #函數的嵌套調用
2 def demo_1(): 3 print(123) 4 def demo_2(): 5 demo_1() 6 print(456) 7 demo_2() 8 # 輸出結果:
9 # 123
10 # 456
11
12 #函數嵌套定義
13 def demo_1(): 14 print(123) 15 def demo_2(): 16 print(456) 17 demo_2() 18 demo_1() 19 # 輸出結果:
20 # 123
21 # 456
注意:內存讀函數的時候先讀定義函數名(不讀裏面的函數體),後面遇到調用此函數的時候,再返回讀函數的函數體。
在函數外調整內部嵌套函數內容的方法:
1 def case(x,y,z): 2 def new_case(a,b,c): 3 print('content',a,b,c) 4 new_case(x,y,z) 5 case(1,2,3) 6 #輸出結果 content 1 2 3
進階:
①到⑦表示代碼運行順序
*args 和 **kwargs 只是函數定義參數的方式,和混合傳參不是一回事哦
在函數外部定義的變量爲全局變量,函數內部定義的變量爲局部變量
在函數內定義的局部變量只在該函數內可見,當函數運行結束後,在其內部定義的全部局部變量將自動刪除而不訪問
1.
1 a = 1
2 b = 2
3 def num_max(a,b): 4 c = b if a<b else a 5 print(c) 6 def num_min(a,b): 7 c = a if a<b else b 8 print(c) 9 num_max(10,8) 10 num_min(5,6)
局部命名空間之間信息不互通,不共享
2.
1 a = 1
2 b = 2
3 def num_max(): 4 c = b if a<b else a 5 print(c) 6 num_max() #輸出結果:2
函數局部命名空間(兒子)能夠用全局命名空間(爸爸)的內容,可是全局命名空間(爸爸)不可使用函數局部命名空間(兒子)的內容
就是 兒子能夠用爸爸的,爸爸不能用兒子的
3.
1 a = 1 2 b = 2 3 def num_max(): 4 def num(): 5 a = 3 6 print(a) 7 num() 8 num_max() #輸出結果:3
對於局部命名空間來講,本身有的話就用本身的,本身沒有再用全局命名空間的
4.
1 a = 1
2 b = 2
3 def num_max(): 4 c = 3
5 def num(): 6 d = 4
7 print(a) 8 num() 9 num_max() #輸出結果:1
兒子沒有的先用爸爸的,爸爸也沒有的話,再用爺爺的
爺爺不能用爸爸,更不能用兒子
爸爸也不能用兒子的
命名空間的加載順序:
1.啓動python
2.內置的命名空間(在哪裏均可以用,好比print()等)
3.加載全局命名空間中的名字 —— 從上到下順序加載
4.加載局部命名空間中的名字 —— 調用該函數的時候,在函數裏從上到下去加載
函數的做用域:
內置的命名空間,在任意地方均可以用
全局的命名空間,在咱們寫的代碼裏任意地方(至關於爺爺,爸爸兒子均可以用爺爺的)
局部的命名空間,只能在本身的函數內使用
global:在函數內部修改全局變量的值
1 a = 1
2 def demo_1(): 3 a =2
4 print(a) 5 def demo_2(): 6 a = 3
7 print(a) 8 demo_2() 9 demo_1() 10 print(a)
打印結果:
需求,在函數裏修改全局變量a = 10,這個時候就用的global:
1 a = 1
2 def demo_1(): 3 global a 4 a =10
5 print(a) 6 def demo_2(): 7 a = 3
8 print(a) 9 demo_2() 10 demo_1() 11 print(a)
打印結果:
nonlocal:在函數內部修改函數上一級的變量值,兒子修改爸爸的值,但不影響爺爺的值,只改一層
nonlocal 只修改局部命名空間裏的 從內部往外部找到第一個對應的變量名
1 a = 1
2 def demo_1(): 3 a =2
4 print(a) 5 def demo_2(): 6 a = 3
7 print(a) 8 demo_2() 9 demo_1() 10 print(a)
打印結果:
需求:修改demo_1()裏a的值爲10
1 a = 1
2 def demo_1(): 3 a = 2
4 print(a) 5 def demo_2(): 6 nonlocal a 7 a = 10
8 print(a) 9 demo_2() 10 demo_1() 11 print(a)
輸出結果:
def func(): pass
func就是函數名,加個括號func()纔是調用函數
函數的名字首先是一個函數的內存地址,能夠看成變量使用 ,函數名是第一類對象的概念
函數的名字能夠賦值,能夠做爲其餘列表等容器類型的元素
函數的名字能夠做爲函數的參數,返回值
1 def func(): 2 print(123)
3 print(func) 4 #輸出結果:<function func at 0x0000023DB22EF1F8>
5 # 是個函數 名爲func 內存地址
就表示func是一個存着一個函數地址的變量而已
因此下面這些均可以使用:
1 def func(): 2 print(123) 3 a = func 4 print(func) 5 print(a) 6 #輸出結果:如出一轍
7 # <function func at 0x000002435074F1F8>
8 # <function func at 0x000002435074F1F8>
1 def func(): 2 print(123) 3 a = func 4 a() #輸出結果:123
1 def func(): 2 print(123) 3 list_1 = [func] 4 print(list_1) #輸出結果 [<function func at 0x000001BC83DCF1F8>]
5 #這個時候 list_1[0] == func
6 list_1[0]() #輸出結果:123 list_1[0]()也能夠調用函數func()
1 def func(): 2 print(123) 3 def exal(q): 4 q() #至關於func(),用到了前面說的嵌套函數的調用
5 print(q,type(q)) 6 exal(func) 7 print(type(func)) 8 #輸出結果:
9 # 123
10 # <function func at 0x0000027B24E5F288> <class 'function'>
11 #<class 'function'>
高階函數:
高階函數定義:
1.函數接收的參數是一個函數名
2.函數的返回值是一個函數名
知足上述條件任意一個,均可稱之爲高階函數
1 def foo(): 2 print('from foo') 3 def test(func_name): 4 return func_name 5 print(test(foo)) #<function foo at 0x0000018F2211F288> 拿到的是foo函數名的內存地址
此時test()就是一個高階函數
內部函數(下面的demo_2)引用了外部函數(dem_1)的 變量,內部的函數就叫作閉包
1 def demo_1(): 2 name = 'zrh'
3 age = '20'
4 def demo_2(): 5 print(name,age) 6 print(demo_2.__closure__) 7 #(<cell at 0x0000018B6DE9A108: str object at 0x0000018B6DE6DDF0>,
<cell at 0x0000018B6DE9A1F8: str object at 0x0000018B6DE6DDB0>)
8 #打印出來有東西說明用到了外部函數的變量,就造成了閉包
9 demo_1()
閉包的做用:
在變量不容易被別人改變的狀況下,還不會隨着你屢次去調用而反覆取建立
1 def demo_1(): 2 name = 'zrh'
3 print(name) 4 demo_1() 5 demo_1() 6 demo_1() 7 demo_1() 8 demo_1() 9 demo_1() 10 #......
若是我執行demo_1函數一萬次。那麼內存就會開闢一萬次空間儲存 name = ‘zrh’,而後再耗費時間關閉那一萬次的空間
1 def demo_1(): 2 name = 'zrh'
3 def demo_2(): 4 print(name) 5 return demo_2 6 i = demo_1() 7 i() 8 i() 9 i() 10 i()
若是用閉包的方式,即便調用函數一萬次,內存也會在第6行代碼執行時建立一次空間來儲存name = ‘zrh’,大大節省空間利用效率
閉包的應用:
1 from urllib.request import urlopen #模塊
2 def get_url(): 3 url = 'http://www.cnblogs.com/'
4 def inner(): 5 ret = urlopen(url).read() 6 return ret 7 return inner 8 get_web = get_url() 9 res = get_web() 10 print(res)
一樣url = 'http://www.cnblogs.com/'只建立了一次,後面調用千百萬次,內存空間只有一次