Day04:函数参数、对象、嵌套、闭包函数和装饰器
上節課復習:
??? 1.什么是函數
??????? 函數就是具備某一功能的工具
??? 2.為何用函數
??????? 1.程序的組織結構和可讀性
??????? 2.減少代碼冗余
??????? 3.擴展性強
??? 3.如何用函數
??????? 函數分為兩大類:
??????????? 內置函數:len
??????????? 自定義函數: 1.有參 2.無參 3.空函數
??????? 語法:
??????????? def函數名(arg1,arg2)
??????????????? '''
??????????????? 注釋
??????????????? '''
??????????????? code1
??????????????? code2
??????????????? return 返回值
??????? 調用函數: 函數名(1,2,3)
??????? 函數必須遵循:先定義,后調用
??????? 定義階段:只檢測語法,與執行函數體代碼
??????? 調用階段:通過函數名找到函數,然后執行函數整體代碼
??????? 函數名:用來訪問函數的內存地址,加上括號用來執行函數
??????? 函數參數:是外調用者為函數體傳值的媒介
??????? 函數體代碼:是函數功能的具體實現
??????? 函數返回值是函數體執行的成果,不寫return默認返回None
??????????? 1.返回值沒有類型限制
??????????? 2.返回值沒有個數限制
??????????????? 無return,默認返回None
??????????????? return值1:返回1
??????????????? return值1,2,3,:返回值(1,2,3)
??????????? return注意點:是函數結束標志,函數體內可以有多個return,但是只要執行一次return,即代表函數結束
1.函數參數的使用
2.函數對象
3.函數嵌套
4.名稱空間與作用域
5.閉包函數(2+3+4)
6.裝飾器 一.函數參數的類型:
? 1.形參與實參
??? 形參:定義函數時,括號內指定的參數,本質就是調用名
??? 實參:調用函數時,括號內傳入的值
??? 只有在調用函數時才會在函數體內發生實參(值)與形參(變量名)的綁定關系
??? 該綁定關系只在調用函數時臨時生效,在調用函數結束時解除綁定 1 def foo(x,y): #括號內x,y 為形參 2 print(x) 3 print(y) 4 foo(1,2) # 括號內1,2為實參
輸出:
1
2
? 2.位置參數:
??? 位置形參:在定義函數時,從左往右的順序依次定義形參稱之為位置形參
??????? 注意:1.但凡是按照位置定義的形參,在調用函數時必須為其傳值,多一個少一個都不行
??? 位置實參:在調用函數時,從左往右的順序依次傳入值稱之為位置實參
??????? 注意:1.在傳值時按照順序與形參一一對應
輸出:
---------------------------------------------------------------------------
TypeError???????????????????????????????? Traceback (most recent call last)
<ipython-input-3-b10bbf76aa4f> in <module>()
2???? print(x)
3???? print(y)
----> 4 foo(1,2) # 括號內1,2為實參
TypeError: foo() missing 1 required positional argument: 'z'
?3.關鍵字實參:
??? 在調用函數時,按照key=value的形式定義的實參,稱之為關鍵字實參
??? 注意:1.在傳值時可以完全打亂順序,但仍然能指名道姓地指定參數的傳值
???????? 2.可以在調用函數時,混用位置實參與關鍵字實參,但是位置實參必須在關鍵字實參的左邊,并且不能為某個形參重復性傳值
???????
輸出:
2
3
4.默認參數:
??????? 在定義函數時,就已經為某些參數綁定值,稱之為默認參數
??????? 注意:
??????????? 1.在定義階段就已經有值,意味在調用階段可以不用為其傳值
??????????? 2.默認形參必須放到位置形參的后面
??????????? 3.默認形參的值只在定義階段生效一次
??????????? 4.默認形參的值通常應該是不可變類型
輸出:
1
2
3
? ? 歸納對比:默認形參vs位置形參:
??????? 默認形參:大多數情況值不變
??????? 位置形參:大多數情況值都是不一樣的
輸出:
x:1
y:2
z:10
輸出:
andy 的愛好是 ['read']
tom 的愛好是 ['read', 'run']
alex 的愛好是 ['read', 'run', 'sing']
輸出:
andy 的愛好是 ['read']
andy 的愛好是 ['read', 'music']
andy 的愛好是 ['read', 'music', 'run']
lily 的愛好是 ['run']
alex 的愛好是 ['sing']
?5.可變長度的參數:
??????? 可變長度指的是在調用函數時,函數參數的個數可以不固定
??????? 然而實參終究是要為形參傳值的,針對兩種形式實參個數不固定,對應形參也必須要有兩種解決方案來分別處理溢出位置實參(*)與溢出的關鍵字實參(**)
輸出:
1
2
(3, 4, 5, 6, 7, 8)
1
2
('h', 'e', 'l', 'l', 'o')
h
e
('l', 'l', 'o')
輸出:
alex tom andy
1 #1.1 形參中帶** 2 #**會將溢出的關鍵字實參存成字典,然后賦值給緊跟其后的變量名 3 4 def foo(x,y,m,n,**z): #**z={'a': 1, 'b': 2, 'c': 3}, 5 print(x) 6 print(y) 7 print(m) 8 print(n) 9 print(z) 10 foo(1,2,n=10,m=20,a=1,b=2,c=3)輸出:
1
2
20
10
{'a': 1, 'b': 2, 'c': 3}
輸出:
1
2
20
10
{'a': 1, 'b': 2, 'c': 3}
輸出:
1
111
20
10
{'a': 1, 'b': 2, 'c': 3}
輸出:
1
1
2
輸出:
(1, 2, 3) {'a': 10, 'b': 20, 'c': 30} --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-31-02b3f05d6305> in <module>() 5 print(args,kwargs) 6 index(*args,**kwargs) ----> 7 wrapper(1,2,3,a=10,b=20,c=30) <ipython-input-31-02b3f05d6305> in wrapper(*args, **kwargs) 4 def wrapper(*args,**kwargs): #args=(1,2,3),kwargs={'a': 10, 'b': 20, 'c': 30} 5 print(args,kwargs) ----> 6 index(*args,**kwargs) 7 wrapper(1,2,3,a=10,b=20,c=30) TypeError: index() got an unexpected keyword argument 'a' 1 #如果需要將外層的函數的參數格式原封不動地轉嫁給內部調用的函數,就需要用到下述方法: 2 def index(name,age,sex): 3 print('name:%s age:%s sex:%s' %(name,age,sex)) 4 5 def wrapper(*args,**kwargs): #args=(1,2,3),kwargs={'a': 10, 'b': 20, 'c': 30} 6 print(args,kwargs) 7 index(*args,**kwargs) #index(*(1,2,3),**{'a': 10, 'b': 20, 'c': 30} 8 #我們雖然調用的是wrapper函數,但是我們遵循的其實是index函數的參數規則 9 wrapper('andy',sex='male',age=18)輸出:
('andy',) {'sex': 'male', 'age': 18}
name:andy age:18 sex:male
輸出:
1 2 4 3
1 #函數是第一類對象,意味著函數可以當作變量去使用 2 #3.可以當作函數的返回值 3 def bar(): 4 return foo 5 f=bar() 1 #4.可以當作容器類型的元素 2 def f1(): 3 print('from f1') 4 def f2(): 5 print('from f2') 6 l=[f1,f2] 7 print(l) 8 l[1]()輸出:
[<function f1 at 0x000001ED436887B8>, <function f2 at 0x000001ED43688620>]
from f2
1.名稱空間與作用域:namespaces
??? 名稱空間是存放名字與值綁定關系的地方
??? 要取到值必須通過名字才能找,而名字又在名稱空間中放著,所以在取值時需要先到名稱空間中找到名字自然就拿到值的內存地址了
2.名稱空間分為三種:
??? a.內置名稱空間:存放python解釋器自帶的名字,生命周期:在解釋器啟動時產生,關閉時回收
??? b.全局名稱空間:除了內置的與局部的之外的名字都屬于全局名稱空間,生命周期:在程序文件執行時就立刻產生,程序執行完畢后就回收
??? c.局部名稱空間:存放的時函數內部定義的名字,生命周期:在調用函數時臨時生效,在調用函數結束時立刻回收
???
??? 加載順序:內置名稱空間--》全局名稱空間--》局部名稱空間
??? 加載名稱空間的目的:為了將名字與值的綁定關系存放起來,而存的目的時為了取,也就是說,當我們在查找名字時,必然時在三者其一中查找
??? 查找順序:局部名稱空間--》全局名稱空間--》內置名稱空間
??? 基于當前所在位置往后查找
? 4.作用域
?????? 作用域指的是作用范圍
?????? 分為:
?????? 全局作用范圍:包含內置名稱空間與全局名稱空間中的名字
????????????? 特點:全局有效
?????? 局部作用范圍:包含的局部名稱空間的名字
????????????? 特點:局部有效,臨時存活
函數的作用域關系是在函數定義階段就已經固定死的
#閉包函數
1.閉指的是-》定義在函數的內部函數
2.包指的是-》該內部函數包含對其外層作用域名字的引用
閉包函數通常需要結合函數對象的概念,將閉包函數返回到外部使用
裝飾器:
??? 裝飾指的是為被裝飾對象添加新的功能
??? 器指的是工具
??? 裝飾器本身可以任意可調用的對象,被裝飾的對象也可以是任意可調用的對象
??? 目標:
??????? 寫一個函數用來為另一個函數添加新功能,需要遵循開放封閉原則(對修改時封閉的,對擴展時封閉的)
??????? 1.不修改被裝飾對象的源代碼
??????? 2.不修改被裝飾對象的調用方式
?
?
?
轉載于:https://www.cnblogs.com/dingchuan/p/9326014.html
總結
以上是生活随笔為你收集整理的Day04:函数参数、对象、嵌套、闭包函数和装饰器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux centosVMware s
- 下一篇: Django基础—— 1.WEB框架介绍