python函式
1.函式作用
- 最大化代碼重用和最小化代碼冗余
- 流程的分解
2.函式基本概念
- def創建物件并賦值給某一變數
## 創建一個函式物件并賦值給fn_name
def fn_name(args1,args2,...,argsN):
<statements>復制代碼
- def是可執行的代碼
## 通過if陳述句判斷來做定義函式,def是實時執行的
if test:
def fn_name():
<statement>
else:
def fn_name():
<statement>
## 分配函式物件
myFn = fn_name
## 呼叫函式
fn_name()復制代碼
- return將結果物件發送給呼叫者
## 函式主體一般都包含return陳述句
def fn_name(args1,args2,...,argsN):
...
return <value>復制代碼
- lambda創建一個物件并將結果回傳
## 生成函式物件的表達形式
lambda argument1, argument2,... argumentN : expression using arguments
## lambda注意點
其一,lambda是運算式而不是陳述句
其二,lambda的主體是一個單個運算式而非陳述句
## 定義一個正常的函式
def func(x,y,z):
return x+y+z
## 使用lambda運算式
f = lambda x,y,z:x+y+z
## 使用默認引數
f = lambda x=1,y=2,z=3:x+y+z復制代碼
- yield向呼叫者發回一個結果物件并記住離開的地方
生成器函式
## 撰寫常規def陳述句并用yield陳述句一次回傳一個結果,在每個結果之間掛起并繼續他們的狀態
## 定義生成函式
def gensquare(N):
for index in range(N):
yield index ** 2
## 等價于以下的函式
def gensquare(N):
yield 0 ** 2 ## 函式每次遇到一個yield便會向呼叫者發送一個回傳值并掛起
...
yield (N-1) ** 2
## yield是發送資料不是回傳資料
## 呼叫生成函式,此時的函式是可迭代,可迭代物件定義了一個__next__方法
for i in gensquare(5):
print(i,end=":")
0 : 1 : 4 : 9 : 16 :復制代碼
生成器運算式
## 串列決議運算式
>>> list = [x**2 for x in range(6)]
[0, 1, 4, 9, 16, 25]
## 生成器運算式類似上述的串列決議但回傳的結果是一個物件而不是一個串列
>>> genrator = (x**2 for x in range(6))
<generator object <genexpr> at 0x1021088e0>
## 執行生成器
>>> next(my_generator)
0
>>> next(my_generator)
1
...
## 撰寫一個串列決議器等同于在一個list內置呼叫中包含一個生成器運算式以迫使其一次生成串列中的所有結果
>>> my_list = list(x**2 for x in range(6))復制代碼
- global宣告函式中模塊級別的變數并進行賦值操作
全域變數
## 全域變數是位于模塊檔案內部的頂層的變數名
X = 80
## 全域變數如果是在函式內被賦值的話,必須經過宣告
def chang_x():
## 必須宣告
global X
X = 90
## 全域變數在函式的內部不經過宣告也可以被參考
def reference_x():
print(X)
## 注意:不同的python檔案(模塊)之間不要使用『模塊物件.屬性名』對全域變數進行修改,最好的方式通過函式修改
## a.py
X = 99
def change_x(new):
global X
X= new
## b.py
import a
a.change_x(97)
## 訪問全域變數的方式
## test.py
var = 99
def local():
var = 0 ## 外面宣告的var與函式內沒關系,當這個函式執行完畢后,var仍然是99
def glob1():
global var ## 告知函式中var是屬于全域變數,直接從全域作用域開始查找,若找不到便會到內置作用域查找,如果還找不到將報錯
var += 1
def glob2():
import dir1.module ## dir1與test.py位于同一個目錄下,module是dir1下的一個模塊,var是module下的全域變數
dir1.module.var += 1
def glob3():
import sys
glob = sys.modules['module'] ## 從搜索路徑中獲取模塊,并對該模塊全域變數進行操作
glob.var += 1復制代碼
- nolocal宣告將要賦值的一個封閉的函式變數,即內嵌一個函式
## 基礎語法
def func():
nonlocal name1, name2, ... # OK here
## nonlocal名稱只能存在于嵌套的def陳述句中,不能出現在模塊的全域作用域或def之外的內置作用域
def tester(start):
state = start ## 資料保存在tester函式物件之中
def nested(label): ## 回傳內嵌的函式物件并且攜帶了外部函式物件的屬性,每次呼叫將改變外部函式物件的屬性state
nonlocal state ## 使用nonlocal宣告state,state必須是在嵌套函式nested提前定義過
print(label, state)
state += 1
return nested
>>> F = tester(0)
>>> F('spam')
spam 0
>>> F('ham')
ham 1
>>> F('eggs')
eggs 2復制代碼
- 函式引數是通過賦值(物件參考)傳遞的
- 不可變引數通過"值"傳遞
- 可變物件通過"指標"進行傳遞
## 引數傳遞是通過自動將物件賦值給本地變數名來實作的
def changer(a,b):
a = 9 # a是值傳遞,屬于當前函式的本地變數
b[-1] = "spam" # b是可變物件通過指標傳遞
## 在函式內部的引數名的賦值不會影響呼叫者
## 改變函式的可變引數的值也許會對呼叫者有影響
def changer(a,b,c):
a = 9 ## 本地變數的值傳遞不影響呼叫者
b[-1] = "spam" ## 函式改變可變物件所指向的內容值
c = c[:] ## 函式內部拷貝副本,不會對呼叫者影響
## 阻止可變物件在函式改變內容值
- 使用拷貝
- 轉成不可變物件,如tuple(list)復制代碼
- 引數、回傳值以及變數不需要在函式中宣告
## python函式沒有型別約束,可以傳遞或回傳任意型別引數
def add(a):
return a ** 2
>>> add(3)
9
>>> add("xiao")
xiaoxiao復制代碼
python賦值引數匹配順序
- 位置:從左至右匹配非關鍵字引數
def func(a,b,c):
print a,b,c
>>> func(1,2,3)
1,2,3復制代碼
- 關鍵字引數:通過匹配變數名稱分配關鍵字引數,與位置無關
def func(a,b,c):
print a,b,c
>>> func(c=3,a=2,b=1)
2,1,3復制代碼
- 其他額外的非關鍵字引數分配到*name元組中
## 任意非關鍵字引數
def func(*args):
print(args) ## 傳遞進來是元組資料并賦值變數名稱為args
## 呼叫
>>> f1(29,34,4,3,12,13)
29,34,4,3,12,13,復制代碼
- 其他額外的關鍵字引數分配到**name字典中
## 任意關鍵字引數
def func(**args):
for key,value in args.items():
print(key +"-->" + value)
## 呼叫
>>> f2(name="xiaoxiao",url="https://www.baidu.com")
url--https://www.baidu.com
name--xiaoxiao復制代碼
如果你有不清楚的可以進我的Python解答交流群:1148633274相互討論學習
- 使用默認值分配給在頭部未得到分配的引數
## 函式定義默認引數值
## 以下函式在定義引數傳遞的時候就已經錯誤,自然呼叫就失敗
def fn(name="xiao",age):
print("the name is "+name+",and the age is "+age)
>>> fn(34) ## 呼叫失敗
SyntaxError: non-default argument follows default argument
>>> fn(age=34) ## 呼叫失敗
SyntaxError: non-default argument follows default argument
## 正常的定義方式是沒有指定默認引數值在前,有默認引數值的定義在后
def fn(age,name="xiao"):
print("the name is "+name+",and the age is "+age)
>>> fn(34) ## 呼叫正常
>>> fn(age=34) ## 呼叫正常復制代碼
python模塊與包
1.模塊
模塊組成
- import:使匯入者以一個整體獲取模塊
- from:允許客戶端從一個模塊中獲取特定的變數名
- imp.reload:在中止py程式中,提供一種重新載入模塊檔案代碼的方法
模塊扮演的角色
- 代碼重用
- 系統命名空間的劃分
- 實作共享服務和資料
import在模塊第一次匯入時執行三個步驟
- 找到模塊檔案,即搜索模塊
- 編譯成位碼
- 執行模塊的代碼來創建所定義的物件
sys.path:即模塊搜索路徑
- 程式的主目錄
- PYTHONPATH目錄
- 標準鏈接庫目錄
- 任何.pth檔案的內容
模塊撰寫
- import將整個模塊物件賦值給一個變數名
- from將一個或多個變數名賦值給另一個模塊中同名的物件
## 相同主目錄
## module1.py
def check(num):
return num>0
## module2.py
import module1
module1.check(9)
## from:把模塊檔案中的一個或者多個變數名從中復制到當前參考的作用域內,此時無需再通過模塊呼叫
from module1 import check
check(9)
## from *:把模塊檔案中所有定義好的變數名復制到當前參考的作用域中
from moudle1 import *
check(9)復制代碼
from與import對等性
from module import name1,name2
等效于
import module
name1 = module.name1
name2 = moudle.name2
del module復制代碼
模塊檔案生成命名空間
- 模塊陳述句在首次匯入時執行
- 頂層的賦值陳述句會創建模塊屬性
- 模塊的命名空間能通過屬性
__dict__或dir(module)獲取 - 模塊是一個獨立作用域(本地變數就是全域變數)
多載模塊:python內置函式reload()
- reload會在模塊當前命名空間內執行模塊檔案的新代碼
- 檔案中頂層賦值陳述句會使得變數名換成新值
- 多載會影響所有使用import讀取模塊的客戶端
- 多載只會對以后使用from的客戶端造成影響
## 使用reload()的時候,模塊是預先加載過的
/main
/dir1
__init__.py
/dir2
__init__.py
dir2module.py
test.py
## main的主目錄加載到搜索路徑中
>>> import dir1.dir2.dir2module
dir1 init.....
dir2 init....
dir2 module py ...
>>> reload(dir1.dir2.dir2module) ## 重新加載dir2module,而不會重新加載dir1和dir2的初始化操作
dir2 module py ...
## 重新加載dir1和dir2
>>> reload(dir1)
>>> reload(dir1.dir2)復制代碼
2.包
包的匯入
- 每一個python模塊包都必須含有
__init__.py檔案 - 增加主目錄到包的搜索路徑中,即PYTHONPATH或者是.pth檔案中
- 模塊搜索路徑的專案提供平臺特定的目錄路徑前綴,之后再在import的路徑左邊添加這些路徑
包的執行
- 包的初始化:匯入某個目錄時,會自動執行改目錄下
__init__.py檔案中的所有程式代碼 - 模塊命名空間的初始化:匯入后會變成真實的嵌套物件路徑
- from 陳述句的行為:可以在
__init__.py定義目錄以from 陳述句形式匯入時,需要匯出什么
## 當前目錄結構:
dir0
/dir1
__init__.py
a.py
/dir2
__init__.py
b.py
/module2
__init__.py
/module3
__init__.py
b.py
test.py
dir0稱為主目錄(__init__.py可有可無),dir1 和 dir2 是模塊包,將主目錄添加到搜索路徑中
## 常規匯入
>>> import dir1.dir2.b ## 匯入后會運行并回傳一個模塊物件
dir1 init..... ## dir1下的__init__.py
dir2 init.... ## dir2下的__init__.py
dir2 module py ... ## dir2下的b.py
## 使用from匯入
>>> from dir1.dir2 import b ## 避免每次讀取時重新輸入路徑
dir1 init..... ## dir1下的__init__.py
dir2 init.... ## dir2下的__init__.py
dir2 module py ... ## dir2下的b.py復制代碼
相對包匯入作用域
- 相對匯入適用于只在包內匯入
- 相對匯入只是用于from陳述句
- 術語含糊不清
## 可以使用from陳述句前面的點號(".")來指定,匯入相對于外圍的包,
## 這樣的匯入只是在包內部搜索而非在搜索路徑(sys.path)搜索
## 目錄結構
dir1
dir2
__init__.py
a.py
test.py
## test.py下
from .dir2 import a ## 和test.py相同包路徑下的dir2檔案夾的a模塊的匯入復制代碼
模塊查找總結
- 簡單模塊通過搜索sys.path路徑串列上每個目錄查找,從左至右
- 包是帶有一個特殊的
__init__.py檔案的Python模塊的直接目錄,可以使用A,B,C目錄路徑語法匯入 - 同一個包檔案中,常規的import陳述句使用將會通過sys.paths規則搜索,而包中的匯入使用from陳述句以及前面的點號,只是檢查包目錄
- 都明白了嗎? 如果你有不清楚的可以進我的Python解答交流群:1148633274相互討論學習
---------本文來源于網路加上自己的見解,如有侵權,請聯系我洗掉
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/8310.html
標籤:Python
上一篇:領取Python安裝包+安裝教程
