主頁 > 軟體設計 > 【保姆級入門系列】阿ken教你學 Python(五) ——函式

【保姆級入門系列】阿ken教你學 Python(五) ——函式

2021-06-11 08:24:08 軟體設計

你好,我是阿ken

我又雙叒叕來了!

藍色、灰色為了解內容,其中藍色多為參考舉例,紅色為重點記憶,

目錄

5.1 函式概述

5.2 函式的基礎知識

5.2.1 函式的定義

5.2.2 函式的呼叫

5.3 函式的引數傳遞

5.3.1 引數的位置傳遞

5.3.2 引數的關鍵字傳遞

5.3.3 引數的默認值傳遞

5.3.4 包裹傳遞

5.3.5 解包裹傳遞

5.3.6 混合傳遞

5.4 函式的回傳值

5.5 變數作用域

5.5.1 區域變數

5.5.2 全域變數

5.6 函式的特殊形式

5.6.1 匿名函式

5.6.2 遞回函式

5.7 時間處理模塊 —— datetime

5.8 代碼抽象與模塊化設計

5.9 本文總結


快速通道:

【保姆級入門系列】阿ken教你學 Python(四)

🐮阿ken:咳咳從此刻開始,調整心情,開始上課!

5.1 函式概述


🐮阿ken:函式是組織好的、可重復使用的、用來實作單一或相關聯功能的代碼段,通過函式的名稱表示和呼叫,函式也可以看作是一段有名字的子程式,可以在需要的地方使用函式名呼叫執行,在學習本文內容之前,其實我們已經接觸過一些函式,比如輸出資訊到命令列視窗的 print() 函式、接收鍵盤輸入資訊的 input() 函式等,

函式是一種功能抽象,它可以完成特定的功能,與黑箱模型的原理一樣,黑箱模型是指所建立的模型只考慮輸入與輸出,而與程序機理無關,現實生活中,應用黑箱原理的實物有很多,比如洗衣機,對于使用者來說,大家只需要了解洗衣機的使用方法,將洗衣粉、水放入,最終得到洗干凈的衣服,這個程序是完全封閉的,對于函式外界不需要了解其內部的實作原理,只需要了解函式的輸入輸出方式即可使用,換言之,呼叫函式時以不同的引數作為輸入,執行函式后以函式的回傳值作為輸出,
函式大體可以劃分為兩類,一類是系統內置函式,它們由 Python內置函式庫提供,例如我們在前面章節中學習的 print()、input()、type()、int() 等函式;另一類是用戶根據需求定義的具有特定功能的一段代碼,自定義函式像一個具有某種特殊功能的容器 —— 將多條陳述句組成一個有名稱的代碼段,以實作具體的功能,

使用函式的好處主要體現在以下幾方面:
(1) 將程式分解成更小的塊(模塊化),
(2) 降低理解難度,提高程式質量,
(3) 減小程式體積,提高代碼可重用性,
(4) 降低了軟體開發和維護的成本,


5.2 函式的基礎知識

🐮阿ken:函式的使用可以分為函式的定義和函式的用兩部分,它只需要定義一次,便可
以無限次地被重復使用,


5.2.1 函式的定義


Python 使用 def 關鍵字定義函式,基本語法格式如下:

def 函式名([引數串列]):
['''檔案字串''']
函式體
[return陳述句]


上述語法的介紹如下:
(1) 關鍵字def:標志著函式的開始,
(2) 函式名:函式的唯一標識,其命:名方式遵循識別符號的命名規則,
(3) 引數串列:可以有零個、一個或多個引數,多個引數之間使用逗號分隔,根據引數的有無,函式分為帶參函式和無參函式,
(4) 冒號:用于標記函式體的開始,
(5) 檔案字串:用于描述函式的功能,可以省略,
(6) 函式體:函式每次呼叫時執行的代碼,由一行或多行Python陳述句構成,
(7) return陳述句:標志著函式的結束,用于將函式中的資料回傳給函式呼叫者,若函式需要回傳值,則使用 return陳述句回傳,否則 return陳述句可以省略,函式在函式體順序執行完畢后結束,

定義函式時,函式引數串列中的引數是形式引數,簡稱為“形參”,形參用來接收呼叫該函式時傳入函式的引數,注意,形參只會在函式被呼叫的時候才分配記憶體空間,一旦呼叫結束就會即刻釋放,因此,形參只在函式內部有效,
定義一個求絕對值的函式,示例如下:

def my_absolute(x):
if x >= 0:
return x
else:
return -x


以上定義的 my absolute() 函式接收引數x,使用 if-else 陳述句區分 x的正負,若 x為正數,它的絕對值就是它本身,直接回傳 x;否則回傳它的相反數,

5.2.2 函式的呼叫

函式定義好之后不會立即執行,直到被程式呼叫時才會生效,呼叫函式的方式非常簡單,一般形式如下:

函式名(引數串列)


以上形式的引數串列為會被傳遞給函式的形參、在函式執行程序中會使用的引數,這些引數是實際引數,簡稱為“實參”,實參可以是常量、變數、運算式、函式等,
呼叫上述中定義好的 my_absolute()函式,代碼如下:

my_absolute(-10.0)


以上代碼中的-10.0是實參,它將被傳遞給函式定義中的形參x,注意,函式在使用前必須已經被定義,否則解釋器會報錯,


程式執行時若遇到函式呼叫,會經歷以下流程:
(1) 程式在函式呼叫處暫停執行,
(2) 為函式傳入實參,
(3) 執行函式體中的陳述句,
(4) 程式接收函式的回傳值(可選)并繼續執行,


定義和呼叫函式 my_absolute() 的完整代碼如下:

def my absolute(x):
if x >= 0:
print(x)
else:
print(-x)
my_absolute(-10.0)
print("---程式結束---")


對以上程式進行分析: Python 解釋器讀取第 1 ~ 5 行代碼時判定此處定義了一個函式,它先將函式名和函式體存盤在記憶體空間中,但不執行;解釋器執行第 6行代碼,由于此處調了 my_absolute() 函式,程式首先暫停執行,將該函式的實參 -10.0 傳遞給形參x (x=-10.0),然后執行函式體內部的陳述句,函式體執行結束之后重新回到第 6行,最后執行第7行的列印陳述句,

5.3 函式的引數傳遞

🐮阿ken:函式的引數傳遞是指將實參傳遞給形參的程序,Python 中的函式支持以多種方式傳遞引數,包括位置傳遞、關鍵字傳遞、默認值傳遞、包裹傳遞、解包裹傳遞以及混合傳遞,本節將針對函式不同的傳參方式進行講解,


5.3.1 引數的位置傳遞


呼叫函式時,默認按照位置順序將對應的實參傳遞給形參,即將第 1個實參分配給第 1個形參,第 2個實參分配給第 2個形參,以此類推,


假設有個用于判斷三角形是否為直角三角形的 is_triangle() 函式, 該函式的定義

具體如下:

def is_triangle(a, b, c):
if a*a + b*b == c*c or a*a + c*c == b*b
or b * b + c * a:
print("是直角三角形")
else:
print("不是直角三角形")


由以上定義可知,is_triangle() 函式需要接收 3個表示三角形各邊邊長 (大于0)的整型引數,呼叫 is_triangle()函式, 傳入 3個整數,代碼如下:

is_triangle(1, 2, 3)


以上代碼中的第 1 個實參 "1 " 會被賦給第 1個形參a,第 2個實參 " 2 " 會被賦給第 2個形參b,第 3個實參 3會被賦給第 3個形參c,

通過位置傳遞方式傳參時實參的個數必須與形參的個數保持一致,否則程式會出現例外,


5.3.2 引數的關鍵字傳遞

🐮阿ken:如果函式中形參的數目過多,開發者很難記住每個引數的作用,這時可以使用關鍵字方式傳遞引數,關鍵字傳遞通過 ” 形參變數名 = 實參 " 的形式將形參與實參關聯,根據形參的名稱進行引數傳遞、它允許實參和形參的順序不一致,

例如,有一個構建URL格式序符中的函式 makeup_url(),該函式有兩個引數:protocal和 address,分別用于接收協議頭和主機地址,它的定義如下所示:

def makeup_url(protocal, address):
print("URL = {}: //{}".format(protocal, address))


通過關鍵字方式傳參時,可以使用如下兩種形式:

makeup_url(protocal='http', address='www.baidu.com')
makeup_url(address='www.baidu.com',protocal='http')


這時,我們無須再關心定義函式時引數的順序,直接在傳參時指定對應的名稱即可,



5.3.3 引數的默認值傳遞


函式在定義時可以給每個引數指定默認值,基本形式為:函式名(引數 = 默認值),這樣在呼叫時既可以給帶有默認值的引數重新賦值,也可以省略相應的實參,使用引數的默認值,


例如,fun(a=1,b=2,c=3)函式中分別為3個引數a、b、c設定了默認值1、2、3,使用fn(a=7,b=8)呼叫函式,此時 a和 b的值7和8將覆寫默認值1和2,但是引數 c保持不變,仍然使用默認值3,默認值傳遞方式并不要求實參與形參的數量相等,

定義 makeup_url() 函式時為引數 protocal 設定默認值,如下所示:

def makeup_url(address, protocal="http"):
print("URL = {}: //{}" .format(protocal, address))


注意,若帶有默認值的引數與必選引數同時存在,則帶有默認值的引數必須位于必選引數的后面,
呼叫 makeup_url() 函式可以使用如下兩種形式:
makeup_url(address='www.itcast.cn')
makeup_url(protocal="https",address='www.baidu.com')

使用第 1種形式呼叫函式時,因為沒有傳值給protocal引數,所以默認會使用該引數的默認值“http";使用第 2種形式呼叫函式時,因為同時傳值給 protocal和 address引數、所以 address引數的新值會替換該引數的默認值,


5.3.4 包裹傳遞


若定義函式時不確定需要傳遞多少個引數,可以使用包裹傳遞,包裹傳遞的關鍵在于定義函式時,在相應的引數前添加 “*" 或 ”**":若在某個引數名稱的前面加 “*",可以元組形式為該引數傳入一組值;若在某個引數名稱前加 “**”,可以關鍵字傳遞形式為該引數傳入一組值,

例如,定義以 “*” 包裹形參 args 的函式test():

def test(*args):
print(args)


呼叫以上定義的 test()函式時可以傳入多個引數,比如傳入 5個引數:

test(1,2,3,4,5)
(1,2,3,4,5)


由以上運行結果可知,test()的引數 args接收了一個包含 5個元素的元組,
例如,定義帶有 “**” 包裹形參 kwargs 的函式 test():

def test(**kwargs):
print(kwargs)


呼叫 test()函式時能夠以關鍵字傳遞的方式傳遞多個引數,例如:

test(a=1, b=2,c=3,d=4,e=5)
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e':5}


由以上運行結果可知,test()的引數 args接收了一個包含 5個鍵值對的字典,

5.3.5 解包裹傳遞


在呼叫函式時,若函式接收的實參為元組或字典型別,可以使用 “*” 和 “**” 對函式引數解包裹,將實參拆分為多個值,并按照位置傳遞方式或關鍵字傳遞方式將值賦給各個形參,

(1) 元組解包裹
下面來看一個對元組解包裹的示例,代碼如下:

def func(a, b, c):
print(a, b, c)
args = (1, 2, 3)
func(*args)


以上代碼先定義了需要接收 3個引數的 func() 函式,然后呼叫 func()函式并向該函式傳入了一個包含 3個元素的元組 args,由于元組 args的前面添加了 “*”,Python 對 kwargs 進行解包裹操作,將 args元組中的 3 個元素拆分為 3個值,并分別按順序賦值給形參a、b、c,

(2) 字典解包裹
下面來看一下對字典解包裹的示例,代碼如下:

kwargs = {'a':1, 'b': 2,'c':3}
func(**kwargs)


以上代碼呼叫了 func() 函式, 并向該函式中傳入了一個包含 3 個鍵值對的字典 kwargs,由于字典 kwargs 的前面添加了 "**",Python 對 kwargs 進行解包裹操作,將字典 kwargs 中的 3 個鍵值對拆分為 3 個值,并分別按引數名稱賦值給形參a、b、c,


5.3.6 混合傳遞

前面介紹了函式引數的若干種傳遞方式,這些方式在呼叫函式時可以混合使用,但是在使用的程序中要注意前后的順序,混合使用的基本原則如下:


(1) 先按照引數的位置傳遞,
(2) 再按照引數的關鍵字傳遞,
(3) 最后按包裹的形式傳遞,

例如,定義一個函式,該函式包含必選引數、默認引數、可變引數和關鍵字引數:

def func(a,b,c=0, *args, **kw):
print ('a =',a,'b =', b, 'c =', c, 'args =', args, 'kw =',kw)


在呼叫 func()函式時,Python 解釋器按斬訓合使用的原則傳遞引數,呼叫函式的示例如下:

func(1,2)  # 按位置傳遞方式將1、2賦值給a、b,c采用默認值0
a=1 b=2 c=0 args = () kw = {}
func(1, 2, c=3)  # 按位置傳遞方式將1、2賦值給a、b,將3賦值給c
a=1 b=2 c=3 args = () kw = {}
 func(1, 2, 3, 'a', 'b')
a=1 b=2 c=3 args = ('a', 'b') kw = {}
 func(1, 2, 3, 'a', 'b', x=99)
a=1 b=2 c=3 args = ('a', 'b') kw = {'x': 99}


呼叫 func()函式時傳入一個元組和字典,可以通過解包裹的形式傳遞引數,例如:

args = (1, 2, 3, 4)
kw = {'x': 99}
func(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw= {'x': 99}


使用混合傳遞時有兩點需要注意:
(1) 若定義函式時引數有默認值,則帶有默認值的引數必須跟在必選引數的后面,
(2) 若呼叫函式時需要混合使用位置傳遞和關鍵字傳遞,則必選引數要出現在關鍵字引數之前,

5.4 函式的回傳值


函式中的 return 陳述句是可選項,可以出現在函式體的任何位置,它的作用是結束當前函式,將程式回傳到函式被呼叫的位置繼續執行,同時將函式中的資料回傳給主程式,


撰寫含有自定義函式 is_capital()的程式,實作判斷鍵盤輸入的字串是否以大寫字母開頭的功能,代碼如下:


def is capital(words):
if ord("A")<=ord(words[0])<=ord("z"):
return '首字母是大寫的'
else:
return '首字母不是大寫的'
result = is_capital("othon") # 將函式回傳的結果交給變數
print(result)


執行程式,程式輸出的結果:

首字母是大寫的


游戲專案通過坐標控制角色位置,角色坐標由 x和 y兩個值決定,這要求與位置相關的函式能夠同時回傳 x和 y兩個值,函式可以回傳兩個值嗎? 答案是肯定的,不僅如此,Python 函式中的 return也可以回傳多個值,當函式使用 return陳述句回傳多個值時,這些值將以元組形式保存,

例如,定義一個控制游戲角色移動的函式 move(),使用 return陳述句回傳反映角色當前位置的 nx 和 ny,代碼如下:

02 control game role. py
import math
def move(x, y, step, angle=0)
nx=x+ step math cos(angle
y =y- step math sin (angle)
return nx, ny
#回傳多個值
result move (100, 100, 60, math. pi/6)
#實際上回傳的是一個元組
print(result)


以上程式定義了 move()函式、使用變數 result 接收了 move()函式回傳的計算結果并將結果列印,列印資訊如下:

(151.96152422706632, 70.0)


由以上結果可知,函式回傳的其實是一個包含兩個元素的元組,

5.5 變數作用域


Python 變數并不是在哪個位置都可以訪問的,具體的訪問權限取決于變數定義的位置,其所處的有效范圍視為變數的作用域,根據作用域的不同,變數可以劃分為區域變數和全域變數,


5.5.1 區域變數

在函式內部定義的變數稱為區域變數,區域變數只能在定義它的函式內部使用,例如,定義一個包含區域變數 count 的函式 test(),在函式的內部和外部分別訪問變數 count,代碼如下:

def test():
count = 0  # 區域變數
print(count) # 函式內部訪問區域變數
test()
print(count) # 函式外部訪問區域變數


執行程式,程式執行的結果如下:

0
Traceback (most recent call last):
File "C:/Users/admin/PycharmProjects/測驗/func.py", line 6, in <module>
print(count)
NameError: name 'count' is not defined


以上程式在列印 count的值之后又列印了錯誤資訊 "name 'count' is not defined“,由此可知,函式中定義的變數在函式內部可使用,但無法在函式外部使用,
區域變數的作用域僅限于定義它的代碼段內,在同一個作用域內,不允許出現同名的變數,


5.5.2 全域變數


全域變數是指在函式之外定義的變數,它在程式的整個運行周期內都占用存盤單元,默認情況下,函式的內部只能獲取全域變數,而不能修改全域變數的值,例如,將前面定義的 test()函式進行調整,如下所示:

count = 10 # 全域變數
def test():
count = 11 # 實際上定義了區域變數, 區域變數與全域變數重名
print(count)
test()
print(count)


以上代碼中首先在 test() 函式外定義了一個全域變數 count,其次在該函式的內部嘗試為 count 重新賦值,然后在函式的內部訪問了變數 count,最后在執行完函式后訪問變數 count,
執行程式,程式執行的結果如下:

11
10


從以上結果可知,程式在函式 test() 內部訪問的變數 count為 1,函式外部訪問的變數為10,也就是說,函式的內部并沒有修改全域變數的值,而是定義了一個與全域變數同名的區域變數,

在函式內部若要修改全域變數的值,需要提前使用保留字 global進行宣告,語法格式如下:

global 全域變數


對以上定義的 test() 函式再次進行調整,在該函式中對全域變數 count進行修改,具體代碼如下所示:

count = 10  # 全域變數
def test():
global count # 宣告 count為全域變數
count += 10 # 函式內修改 count變數
print(count)
test()
print(count)


以上代碼首先定義了變數 count并賦值為10,其次在 test() 函式內部使用 global保留字宣告 count為全域變數,然后重新給 count變數賦值并將其輸出,最后在函式執行完以后再次輸出,
執行程式,程式執行的結果如下:

20
20


觀察執行結果,程式在函式內部和外部獲得的變數 count的值均為20,由此可知,在函式內部使用關鍵字 global對全域變數進行宣告后,函式中對全域變數進行的修改在整個程式中都有效,

多學一招:LEGB法則
Python 中的作用域大致可以分為以下 4種
(1) L(local):區域作用域,
(2) E(enclosing):嵌套作用域,
(3) G(global):全域作用域,
(4) B(built-in):內置作用域,
基于 LEGB 法則,搜索變數名的優先級是:區域作用域>嵌套作用域>全域作用域>內置作用域,當函式中使用了未確定的變數名時,Python 會按照優先級依次搜索 4個作用域,以此來確定該變數名的意義,首先搜索區域作用域 (L),其次是上一層函式的嵌套作用域 (E),然后是全域作用域 (G),最后是內置作用域(B),按照 LEGB原則查找變數,在某個區域內若找到變數,則停止繼續查找;若一直沒有找到變數,則直接引發 Name Error 例外,


5.6 函式的特殊形式


🐮阿ken:除了前面介紹的普通函式之外,Python 還有兩種具有特殊形式的函式:匿名函式和遞回函式,

5.6.1 匿名函式


匿名函式是一類無須定義識別符號的函式,它與普通函式一樣可以在程式的任何位置使用,但是在定義時被嚴格限定為單一運算式,Python 中使用 lambda關鍵字定義匿名函式,它的語法格式如下:

lambda <形式引數串列>: <運算式>


與普通函式相比,匿名函式的體積更小,功能更單一,它只是一個為簡單任務服務的物件,它們的主要區別如下:
(1) 普通函式在定義時有名稱,而匿名函式沒有名稱,
(2) 普通函式的函式體中包含有多條陳述句,而匿名函式的函式體只能是一個運算式,
(3) 普通函式可以實作比較復雜的功能,而匿名函式可實作的功能比較簡單,
(4) 普通函式能被其他程式使用,而匿名函式不能被其他程式使用,

定義好的匿名函式不能直接使用,最好使用一個變數保存它,以便后期可以隨時使用這個函式,例如,定義一個計算數值平方的匿名函式,并賦值給一個變數:

temp = lambda x : pow(x, 2) # 定義匿名函式, 它回傳的函式物件賦值給變數 temp


此時,變數 temp可以作為匿名函式的臨時名稱來呼叫函式,示例如下:

temp(10)
100


5.6.2 遞回函式

遞回是指函式對自身的呼叫,它可以分為以下兩個階段:
(1) 遞推:遞回本次的執行都基于上一次的運算結果,
(2) 回溯:遇到終止條件時,則沿著遞推往回一級一級地把值回傳來,
遞回函式通常用于解決結構相似的問題,其基本的實作思路是將一個復雜的問題轉化成若干個子問題,子問題的形式和結構與原問題相似,求出子問題的解之后根據遞回關系可以獲得原問題的解,遞回有以下兩個基本要素:
(1) 基例:子問題的最小規模,用于確定遞回何時終止,也稱為遞回出口,
(2) 遞回模式:將復雜問題分解成若干子問題的基礎結構,也稱為遞回體,

遞回函式的一般形式如下:

def 函式名稱 (引數串列):
if 基例:
return 基例結果
else:
return 遞回體


由于每次呼叫函式都會占用計算機的一部分記憶體,若遞回函式未提供基例,函式執行后會回傳 " 超過最大遞回深度 " 的錯誤資訊,
遞回最經典的應用就是階乘,例如,求n的階乘,數學中使用函式 fact(n)表示:

fact(n)=n!=1*2*3*…*(n-1)*n=fact(n-1)*n

在程式中定義 fact()函式實作階乘計算,可以寫成如下形式:

def fact(n):
if n == 1: # 基例
return 1
else:
return fact(n-1)*n # 遞回體


fact(n) 是一個遞回函式,當n大于1時,fact() 函式以 n-1作為引數重復呼叫自身直到 n為1時呼叫結束,開始通過回溯得出每層函式呼叫的結果,最后回傳計算結果,

[回頭補一個遞回程序表]


斐波那契數列也是遞回的一個經典案例,斐波那契數列又稱黃金分割數列,這個數列從第 3項開始,它的每一項都等于前兩項的和,在數學上,斐波納契數列以遞推的方式定義,具體如下所示:

F(1)=1, F(2)=1, F(n)=F(n-1)+F(n-2) (n>=3, n∈N*)


根據以上定義,斐波那契數列的前 9項依次為:1、1、2、3、5、8、13、21、34,
斐波那契數列由數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為 " 兔子數列 ",兔子繁殖的故事是這樣的,一般兔子在出生兩個月后就有繁殖能力,對兔子每個月能生出一對小兔子來,如果所有的兔子都不死,那么一年以后一共有多少對兔子?

第1個月, 兔子沒有繁殖能力,此時兔子的總數量為1對,
第2個月, 免子擁有了繁殖能力,生下一對小免子,此時兔子的總數量為2對,
第3個月, 兔子又生下一對小兔子,而小兔子沒有繁殖能力,此時兔子的總數量為3對,

依此類推,可以得知,經歷 0或 1個月份后,兔子的總數量均為1,之后每經歷一個月份,兔子的總數量為前兩個月份的數量和,例如,經過 3個月時兔子的總數量為1+2=3,經過 4個月時兔子的總數量為 2+3=5,經歷 5個月時兔子的總數量為 3+5=8,

使用代碼實作計算兔子數列的函式,具體如下所示:

def rabbit(month):
if month <= 1:
return 1
else:
return rabbit(month-1) + rabbit(month-2)


以上代碼定義了一個遞回函式 rabbit(),該函式接收一個代表經歷的月份的引數 month,并在代碼段中使用 if-else 陳述句區分了 1月份和其他月份的不同,若是經過了一個月,則回傳總數量為1,代表著遞回函式的出口,若是經過了N (大于1)個月,則會重復呼叫 rabbit()函式,回傳 rabbit(month-2) 與 rabbit(month-1) 的和,

在解釋器中定義 rabbit()函式,并使用以下陳述句呼叫該函式,可計算出經過一年以后,兔子的總數量為:

rabbit(12)
233


5.7 時間處理模塊 —— datetime


🐮阿ken:Python 提供了專門操作日期與時間的 datetime模塊,該模塊提供了很多處理日期與時間的方法,使用這些方法可以從系統中獲得時間,并以用戶選擇的格式進行輸出,
datetime 模塊以格林尼治時間為基礎,將每天用 3600×24 秒精準定義, datetime 模塊中定義了兩個常量:datetime.MINYEAR 和 datetime.MAXYEAR,這兩個常量分別表示最小年份 (1)和最大年份 (9999) ;datetime 模塊還定義了 6個核心的類:

datetime 模塊的核心類:

類名說明
date表示具體日期,精確到天
time表示具體的時間,可精確到微秒
datetime表示具體的日期時間,可以理解為 date和 time
timedelta表示具體的時間差
tzinfo表示日期與時間的時區
timezonetzinfo 抽象基類,表示與 UTC的固定偏移量


上表中的前 3個類最為常見,接下來分別對這 3個類中的常用方法進行介紹:

1. date類


date 類表示理想化日歷中的日期,由年、月和日組成,比如 1998年1月1日,最簡單的創建日期的方式是使用 date類的構造方法,該函式的語法格式如下:

class date(year, month, day)


以上函式中每個引數都只能是整型,它們的含義如下:
(1) year:指定的年份,MINYEAR ≤ year ≤ MAXYEAR,
(2) month:指定的月份,1 ≤ month ≤ 12,
(3) day:指定的日期,1 ≤ day ≤ 給定月份和年份中的天數,
例如,創建一個表示 2019年1月4日的日期物件,代碼如下所示:

 from datetime import date
 date(2019, 1, 4)
 date time.date(2019, 1, 4)


2. time 類


time 類是 datetime 模塊中用于處理時間的類,表示一天中的(本地)時間,由時、分、秒以及微秒組成,比如 12點 0分 0秒,通過 time類的構造方法可以創建一個時間物件,該函式的語法格式如下:

datetime.time(hour=0, minute=0, second=0, microsecond=0)


以上函式中每個引數的含義如下:
(1) hour:指定的小時,0 ≤ hour < 24,
(2) minute:指定的分鐘數,0 ≤ minute < 60,
(3) second:指定的秒數,0 ≤ second < 60,
(4) microsecond:指定的微秒數,0 ≤ microsecond < 1 000 000,

例如,創建一個表示 12時 10分 30秒的時間物件,代碼如下所示:

 from datetime import time
 time(12, 10, 30)
 datetime.time(12, 10, 30)


3. datetime 類


datetime 類可以視為 date類與 time類的結合體,它可以同時表示日期和時間,例如 1970年1月1日0時0分0秒,創建 datetime物件的常見方法有以下4個:
(1) datetime():datetime 類的構造方法,用于構造一個指定日期和時間的 datetime物件,可精確到微秒,
(2) today():獲取一個表示本地當前日期和時間的 datetime物件,
(3) now():獲取一個表示當前時區日期和時間的 datetime物件,
(4) utcnow():獲取當前日期和時間對應的 UTC (世界標準時間)物件,


通過 datetime()方法可以直接構造一個日期時間物件,該方法中引數的含義與 date() 和time() 方法中引數的含義相同,此處不再贅述,例如,創建一個表示 2018年 6月 1日 12點 12分 30秒 50微秒的物件,如下所示:

from datetime import datetime
datetime(2018, 6, 1, 12, 12, 30, 50)
datetime.datetime(2018, 6, 1, 12, 12, 30, 50)


通過 today()方法獲取本地當前的日期與時間,時間會精確到微秒,如下所示:

datetime.today()
datetime.datetime(2019, 1, 4, 14, 33, 8, 248797)


通過 now()方法可以獲取指定時區的日期和時間,時間同樣會精確到微秒,若不指定時區,回傳本地的日期與時間,作用等同于 today()方法,例如,獲取本地當前的日期與時間,如下所示:

datetime.now()
datetime.datetime(2019, 1, 4, 14, 39, 45, 780534)


通過 utcnow() 方法可以獲取當前日期和時間對應的 UTC時間 (世界標準時間),時間仍然會精確到微秒,例如,今天的日期是 2019年 1月 4日,所處東八區的具體時間是 14時 45分,當前所對應的世界標準時間為:

datetime.utcnow() 
datetime.datetime(2019, 1, 4, 6, 45, 9, 505050)


創建好 datetime物件以后,可以使用物件的屬性和方法進一步控制時間的輸出格式,


datetime類的常用屬性

屬性說明
year回傳日期包含的年份
month回傳日期包含的月份
day回傳日期包含的日
hour回傳日期包含的小時
minute回傳日期包含的分鐘
second回傳日期包含的秒鐘
microsecond回傳日期包含的微秒

此外,datetime 類中還提供了常用的格式化日期字串的 strftime() 方法,可以使用任何通用的格式輸出時間,

strftime() 方法控制符

格式控制符說明
%Y四位數的年份表示,取值范圍為0001 ~ 9999
%m月份(01 ~ 12)
%d月內中的一天
%B本地完整的月份名稱,比如 January
%b本地簡化的月份名稱,比如 Jan
%a本地簡化的周日期
%A本地完整周日期
%H24小時制小時數(0 ~ 23)
%I12小時制小時數(01 ~ 12)
%p本地 A.M. 或 P.M. 等價符
%M分鐘數(00 ~ 59)
%S秒(00 ~ 59)


例如,創建一個 datetime物件,以形如 " 時-分-秒 年-月-日 " 的格式進行輸出,代碼如下:

 date_time = datetime.now()
 date_time
 datetime.datetime(2019, 1, 4, 17, 15, 58, 255314)
 date_time, strftime("%H-%M-%S %Y-%m-%d") # 回傳格式化日期
 '17-15-58 2019-01-04'


多學一招:格林尼治時間
我們平時所使用的時間,是以太陽在天空中的方位作標準來計量的,每當太陽轉
到夭球子午線的時刻,就是當地正午12時,由于地球自轉,地球上不同地點看到太
陽通過天球子午線的時刻是不一樣的,例如,當英國倫敦是中午12點時,北京正值
晚上7時45分,上海則是晚上8時06分,
為了使用方便,人們把全球劃分成24個時區,毎個時區跨經度為15度,英國原
格林尼治天文臺所在的時區叫作零時區,包括西經7.5度到東經7.5度范圍內的地區,
在這個時區里的居民都采用原格林尼治天文臺的時間,零時區以東第一個時區,叫作
東一區,從東絲75度到225度,是用東經15度的時間作標準的,再往東順次是東
區、東三區……直到東十二區,每跨過一個時區,時間正好相差1小時,同樣地,
零時區以西順次劃分為西一區、西二區……一直到西十二區(西十二區就是東十二
區)世界各地都包括在這24個時區里,每個時區的時間是統一的,稱為區時,
中國位于格林尼治東面,使用的是東經120度的標準時間,屬于東八區,我們日
常所說的“北京時間**點”就是東八區的標準時間,


5.8 代碼抽象與模塊化設計


函式的特點主要體現在兩個方面:代碼抽象和模塊化設計,關于它們的介紹分別如下:

1. 代碼抽象

程式由一系列的代碼組成,若代碼無序且無組織,不僅不利于開發人員的閱讀與理解,后期也很難開發與維護,為了形成易于理解的結構,避免撰寫出面條式代碼 (非結構化和難以維護的源代碼),需要對代碼進行抽象,通常采用函式和物件兩種抽象方式抽象代碼,
函式將一段代碼封裝起來并對其命名后供其他程式呼叫,函式的優點有很多,最直接的優點就是實作代碼復用,函式定義之后可以在程式中多次被呼叫,從而避免重復撰寫具有相同功能的代碼,
物件是程式的一種高級抽象方式,它將一段代碼組織成更高級別的類,類是一組具有相同屬性和方法的物件集合,描述了屬于該物件的所有性質,物件存在于現實世界中,比如大學生、汽車、空調等,物件包括描述特征的屬性和描述行為的方法,例如,大學生是—個物件,姓名、年齡等是屬性,跑步、學習、思考等是方法,

函式和物件分別是面向程序編程思想和面向物件編程思想的核心,面向程序是種以程序描述為中心的編程方式,它要求開發人員列出解決問題所需要的步驟,然后用函式將這些步驟逐個實作,使用時依次建立呼叫函式的陳述句即可;面向物件編程是一種組織程式的新型思維方式,這種思維方式會將資料和操作封裝到一起,組成一個相互依存、不可分離的整體 ——物件,
面向物件程式設計的焦點不再是程序,而是物件及物件間的關系,此種思想提取同一型別事物的共性構造出類,在類中設定這一類事物的共同屬性,為類定義與外界發生關系的介面 ——方法,
面向程序與面向物件是兩種不同的編程方式,它們的抽象級別有所不同,所有能通過面向物件編程實作的功能都可以采用面向程序完成,兩者在解決問題上并不存在優劣之分,具體采用哪種方式取決于開發要求,一般在撰寫大規模程式時建議采用面向對
象的編程方式,
Python 語言同時支持面向物件和面向程序兩種編程方式,本系列文采用面向程序的方
式撰寫程式,但 Python3 內部代碼全部采用面向物件方式實作,為降低讀者的理解難
度,阿ken 在講解和使用 Python模塊時會涉及面向物件 (呼叫類的函式創建物件、調
用物件的方法操作物件)

2. 模塊化設計

模塊化設計是指通過函式或物件的封裝功能將程式劃分成主程式、子程式、子程
序與子程式間關系的表達,它體現的是分而治之的思想,
針對復雜問題的求解所采用的模塊劃分通常是從功能的角度進行的,劃分后的模塊要具備 " 相對獨立、功能單一 " 的特征,也就是說,一個好的模塊必須具有高度的獨立性和較強的功能,在實際應用中,通常會用如下兩個指標從不同的角度對模塊的劃分情況加以度量,
(1) 內聚度:是對模塊內各元素之間相互依賴性大小的度量,內聚度越大,模塊內各元素之間聯系越緊密,其功能越強;反之,低內聚模塊內各元素的關系較為松散,
(2) 耦合度:是對模塊之間相互依賴程度的度量,耦合度越低,模塊的相對獨立性越大;耦合性越高,一個模塊受其他模塊的影響越大,
模塊劃分時應當盡可能降低不同模塊間的關聯,提升單一模塊自身的功能性,做
到 " 高內聚、低耦合 ",
采用模塊結構設計程式的好處在于:整個程式結構清晰,易于分別撰寫與除錯,便于維護與呼叫,并利于程式功能的進一步擴充與完善,

5.9 本文總結

本章首先介紹了函式的概念、定義和呼叫,其次介紹了函式引數傳遞的幾種方式,然后介紹了變數作用域和兩個具有特殊形式的函式:匿名函式和遞回函式,之后介紹了日期時間處理模塊 datetime,最后介紹了代碼重用與模塊化設計的思想,通過對本文的學習,讀者應能夠理解函式式編程的優越性,可以按照需求靈活定義函式,

后來你常常會遇到更優秀的人

可能也會跟我一樣經常感覺自己是個 loser

但后來想起來Kobe的一句話:如果一定有人會贏,那個人為什么不能是我呢?

而今故人已逝,隨著年紀增長,我也漸漸懂了這句話背后的艱辛和努力

也常常用這句話勉勵尚在低谷階段的自己

不管怎樣

我一定要贏

Peace

快速通道:

【保姆級入門系列】阿ken教你學 Python(四)

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/286636.html

標籤:其他

上一篇:失戀了好難受,用Python爬網易云歌曲評論看有多少人跟我一樣,看完更難受了...

下一篇:依賴服務故障怎么辦?幾百萬的專案明天要路演Demo了

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more