python04-三元運算、定義函數、函數參數詳解、函數嵌套、函數命名空間、函數名的靈活應用、閉包

目錄:python

1.三元運算web

2.定義函數數組

3.函數參數詳解閉包

4.函數嵌套app

5.函數命名空間函數

6.函數名的靈活應用url

7.閉包spa

一.三元運算3d

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/'只建立了一次,後面調用千百萬次,內存空間只有一次

相關文章
相關標籤/搜索