### 子產品化程式設計
> 子產品化程式設計指把程式進行封裝(函數封裝,面向對象,檔案。。。)
#### 什麼是函數?
> function -> 函數,功能
>
> 函數就是一個具有特定功能的代碼塊
#### 函數的作用?
> 函數就是把代碼進行封裝,以提高代碼的重用性,提高開發效率,并且降低了後期的維護成本
#### 函數的定義和使用
```python
# 定義函數【基本結構】
def 函數名([參數清單]):
目前函數的具體功能的代碼
目前函數的具體功能的代碼
。。。。
# 函數封裝完并不會執行,隻是把函數定義了而已
# 如果想使用定義的函數,那麼就需要用文法來進行函數的調用
# 函數的調用
函數名()
```
#### 函數的特征及注意事項
1. 函數定義後,不調用不執行
2. 不能在函數定義前調用函數
3. 函數的調用不受次數影響
4. 函數的命名要遵守命名規範
+ 字母數字下劃線,不能以數字開頭
+ 嚴格區分大小寫,不能使用關鍵字
+ 命名最好有意義,且不要使用中文
5. 函數名不要沖突,沖突後會被覆寫
### 關于函數的參數
> 函數在定義時,可以在參數清單的位置定義形參
>
> 如果函數有形參,那麼在函數調用時也需要給定參數
>
> 實參将值傳遞給形參的過程,本質上就是變量指派操作
#### (1)函數參數概念及分類
函數參數:調用時需要傳遞的資料.
函數參數大類分為形參和實參:
. 形參意思: 函數定義時的參數
. 實參意思: 函數調用時的參數
形實關系:函數調用時,形參和實參個數需要一一對應
形參種類: 普通參數,預設參數,普通收集參數,命名關鍵字參數,關鍵字收集參數
實參種類: 普通實參,關鍵字實參
#### (2)普通參數
(位置參數)普通的參數,接收實參傳遞的值
#### (3)預設參數:
> 位于普通參數後面,具有預設值的參數
>
> 文法:(x,y=2) y就是預設參數
#### (4)收集參數:
> 專門收集在函數調用時傳遞的多餘的實參
```
1.普通收集參數:專門用于收集多餘的普通參數,形成一個新的元組
文法:參數前面加* 例:*args
2.關鍵字收集參數:用于專門收集多餘關鍵字實參,形成一個新的字典
文法:參數前面加** 例:**kwargs
```
#### (5)命名關鍵字參數
> 定義時放在*号後面的參數,調用時強制必須傳入指定參數名才能調用
```
文法:(a,*,x) x是命名關鍵字參數
如果函數參數中已經有了收集參數,那麼收集參數後面的參數即為命名關鍵字參數
文法:(*args,x,y)
```
#### (6)形參聲明的位置順序:
> 普通參數 -> 預設參數 -> 收集參數 -> 命名關鍵字參數 -> 關鍵字收集參數
```
def func(a,b,c=1,*args,d,**kw)
a,b為普通參數,c是預設參數,args是收集參數,d是命名關鍵字參數,kw是關鍵字收集參數
極少出現五種參數同時出現的情況
def func(a,b=2,*,c,d,**kw)
a為普通參數,b是預設參數,c,d是命名關鍵字參數 ,kw是關鍵字收集參數
```
#### 所有參數的擺放問題
- 實參:普通實參在前,關鍵字參數在後
- 形參:
- 關鍵字收集參數一定在最後出現
- 收集參數推薦在普通參數之後使用
- 推薦順序:普通形參,收集參數,關鍵字收集參數
### 函數傳回值
> 一個函數除來可以完成一定功能之外,還可以按需要傳回一些内容
>
> 函數中使用 return 關鍵字來指定傳回資料,可以傳回任意類型的資料
>
> 函數的傳回值,會把資料傳回到調用處,可以使用變量接收,或其它處理
```
函數可以分為兩類
1。執行過程函數: 函數體内完成一定的功能既可,沒有傳回值
2。具有傳回值的函數: 函數體内完成一定的功能,并且傳回一個結果到函數調用處
```
#### return傳回值的特征
+ 函數中可以使用 return 進行資料的傳回
+ 可以使用return 傳回 任意内容或資料
+ return 會把傳回值,傳回到函數調用出
+ return 意味着函數的結束,return之後的代碼不在執行
+ 如果在函數中沒有使用return 或者 return後面沒有任何内容,那麼預設傳回 None
```python
# 假設有這樣一個需求,定義一個函數,完成兩個數的計算,并把結果輸出
# def jia(n1,n2):
# res = n1+n2
# print(res)
# jia(2,5)
# 需求改變,定義一個函數,完成兩個數的計算,并把結果傳回
def jia(n1,n2):
res = n1+n2
return res
r = jia(2,4)
print(r)
```
### 變量作用域
> 作用域就是目前起作用,可用的範圍區域
>
> 變量的有效範圍
全局變量:在函數内外都可以使用的變量
局部變量:在函數内部可以使用的變量
```
局部變量
函數内定義的變量,局部變量,在函數外不能使用
全局變量
在函數内部使用 global 直接定義的變量,就是全局變量,函數内外都可以使用
在函數外定義的變量,在函數内使用 global 關鍵字進行聲明,那麼也是全局變量
globals() 擷取全局資料
locals() 擷取目前作用域的資料
在函數外定義的變量,函數可以通路,但是不能更改
資料類型的分類:
可變資料類型:在函數外定義的變量,在函數可以使用,
清單和字典
不可變資料類型:在函數外定義的變量,在函數内隻能通路,不能使用其它操作
```
#### 不光變量有作用域,函數一樣也有相同的作用域
```python
def outer():
print('this is outer function...')
# 在函數内定義的函數,稱為 局部函數,函數外無法使用
def inner():
print('this is inner function...')
inner()
outer()
# inner()
```
### nonlocal
> 在内函數中如何使用上一層函數中的局部變量?
> 在内函數中如果想使用外層函數的變量,那麼需要使用 nonlocal 關鍵字 引用
> 可以引用上一層函數中定義的局部變量,但依然不能提升為全局變量
```python
# 定義一個外層函數
def outer():
# 外函數的局部變量
num = 10
# 内函數,局部函數,在函數的内部定義的函數
def inner():
# nonlocal 關鍵字在局部函數中使用,
nonlocal num # 可以引用上一層函數中定義的局部變量,但依然不能提升為全局變量
num += 1
print(num)
inner()
outer()
# print(num)
```
#### 關于函數的文檔
```python
def outer():
'''
這裡是讓你些目前函數的文檔說明的。
需要說明目前函數的作用,
如果目前函數還有行參,那麼也需要對行參進行一一說明
name: 這個是一個name參數,有什麼作用。。。
age : 這個表示目前的一個年齡
:return: 此處說明目前函數的傳回值。。。
'''
print(globals())
print(__name__) # 擷取目前腳本的檔案名,
print(__doc__) # 擷取目前腳本的說明文檔
# print(outer.__doc__) # 擷取目前函數的說明文檔
'''
魔術變量
__name__ ==> 目前腳本如果作為主程式,那麼值是 __main__,如果是當做一個子產品,在另外一個腳本中引用去使用,那麼值就是目前檔案的名字
__doc__ ==> 目前腳本的文檔說明 在目前腳本當中的第一個 三引号注釋就是目前腳本的說明文檔
{
'__name__': '__main__',
'__doc__': '\n在内函數中如果想使用外層函數的變',
'__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x110444350>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': '/Users/yc/Desktop/code/8.nonlocal關鍵字.py',
'__cached__': None, 'outer': <function outer at 0x1104938c0>
}
'''
```