PS:原先是想直接進入功能開發,要用到什么函數時再創建,這樣也容易熟悉每個函數的由來和使用方法,但考慮到這樣操作,到時會經常在不同文件間切換,不好描述,容易造成混亂,所以還是使用函數庫這種方式來說明。
下面來說說工具函數包,如果想要快速學會一個新的框架,首先要做的事情就是熟悉工具函數包,一方面,能快速知道有哪些基本功能可以直接調用,不用重復造輪子;另一方面,查看項目代碼時,會比較快的進入角色,能看明白很多代碼是做什么用的,因為工具函數包被調用的機率是最大的。
那么怎么學習呢?當然是有節奏有計划的一步步深入了,我們可以從上到下逐個查看研究,通過查看代碼,我們可以基本了解這個包有什么功能,但也僅僅是了解而已,想要真正掌握,必須要去使用它們,最直接的方法就是編寫測試用例進行測試,這樣就可以很快熟悉並掌握這些函數具體有什么功能與限制。
PS:大家在學習工具函數,或其他封裝好的類或函數時,在開始時不需要去知道它里面每一行代碼是做什么用的,為什么要那么寫,只需要知道輸入什么參數會得出什么值就可以了,這就是大家所說的封裝。我們要開汽車,不需要知道它是怎么造出來的,發動機是怎么運行的,只需要知道怎么操作(接口)就可以了。
我以前遇到過幾位愛鑽牛角尖的開發者,想弄明白每一行代碼為什么要那樣寫,當那一行所調用的函數看不懂時,就會再深入一層,看看它更底層是什么原理......就這樣,一般人用幾分鍾就可以知道怎么用的,他花幾天也弄不明白,花了好長時間也沒法寫代碼。對於初學者來說,學習一個函數怎么使用,不要鑽牛角尖,去研究它的內部是怎么運行的,要研究也要等到你以后精通了再說,不然你看到一個函數就去看它的源碼,然后源碼中又會調用其他庫的源碼,其他庫的源碼又會調用python的內核代碼,難道你要搞定python的內核代碼后才可以開始開發嗎?你能搞的定python內核你就是超級大牛了,可以自己開發一種新語言出來了。
所以說想要快速學習,最好的辦法就是知道這個封裝好的函數是干嘛的,它需要輸入什么參數,會返回什么內容就已經夠了。而最快的熟悉方法就是寫單元測試,用你能想到的辦法去測試,這樣就知道什么時候出錯,什么時候正常。
熟悉相關工具函數:
convert_helper.py是類型轉換包,所有字符串轉數值、字符串轉日期、字符串日期轉時間戳等各種類型轉換函數,都可以放到這里來。

1 #!/usr/bin/evn python 2 # coding=utf-8 3 4 import decimal 5 import datetime 6 7 8 ############################################# 9 # 數值型轉換函數 10 ############################################# 11 def to_int(text): 12 """將字符串安全轉換為int類型,轉換失敗時默認值為0""" 13 try: 14 return int(text) 15 except: 16 return 0 17 18 19 def to_int0(text): 20 """將字符串安全轉換為int類型,當int值小於0時,返回0""" 21 result = to_int(text) 22 23 # 判斷轉換后的結果值是否小於0,是的話返回0 24 if not result or result < 0: 25 return 0 26 else: 27 return result 28 29 30 def to_int1(text): 31 """將字符串安全轉換為int類型,當int值小於1時,返回1""" 32 result = to_int(text) 33 34 # 判斷轉換后的結果值是否小於1,是的話返回1 35 if not result or result < 1: 36 return 1 37 else: 38 return result 39 40 41 def to_float(text): 42 """將字符串安全轉換為float類型""" 43 try: 44 return float(text) 45 except: 46 return 0.0 47 48 49 def to_decimal(text): 50 """將字符串安全轉換為int類型""" 51 try: 52 return decimal.Decimal(text) 53 except: 54 return 0 55 56 57 ############################################# 58 # 日期型轉換函數 59 ############################################# 60 def to_datetime(text): 61 """字符串轉時間""" 62 if not text: 63 return None 64 65 # 定義字典根據時間字符串匹配不同的格式 66 time_dict = { 67 1: "%Y-%m-%d %H:%M:%S.%f", 68 2: "%Y-%m-%d %H:%M", 69 3: "%Y-%m-%d %H:%M:%S", 70 } 71 # 如果中間含有時間部分就用:判斷 72 try: 73 if str(text).find('.') > -1: 74 return datetime.datetime.strptime(text, time_dict[1]) 75 elif ':' in text: 76 time_list = text.split(':') 77 return datetime.datetime.strptime(text, time_dict[len(time_list)]) 78 else: 79 return datetime.datetime.strptime(text, "%Y-%m-%d") 80 except: 81 return None 82 83 84 def to_date(text): 85 """字符串轉日期""" 86 d = to_datetime(text) 87 if d: 88 return d.date() 89 90 91 def to_timestamp10(text): 92 """將時間格式的字符串轉化為長度為10位長度的時間戳""" 93 d = to_datetime(text) 94 if d: 95 return int(d.timestamp()) 96 else: 97 return 0 98 99 100 def to_timestamp13(text): 101 """將時間格式的字符串轉化為長度為13位長度的時間戳""" 102 d = to_datetime(text) 103 if d: 104 return int(d.timestamp() * 1000) 105 else: 106 return 0
比如說字符轉int函數
def to_int(text): """將字符串安全轉換為int類型,轉換失敗時默認值為0""" try: return int(text) except: return 0
這里我們用try...except...來捕捉轉換函數出現的異常,當出現異常時我們設置它的默認值為0,讓我們的系統變的更加健壯,不會因為轉換失敗而崩潰。
使用這個函數轉換出現異常時,我們只是直接將它轉換為0,不做記錄,因為數值轉換時直接拋出異常會讓用戶體驗更差勁,另外對於數值類型來說,如果得出的結果都是0而不是期望值,這也很容易排查出來,在后面章節會講到web端接收到的請求值都會記錄下來,方便我們排錯。
def to_int0(text): """將字符串安全轉換為int類型,當int值小於0時,返回0""" result = to_int(text) # 判斷轉換后的結果值是否小於0,是的話返回0 if not result or result < 0: return 0 else: return result def to_int1(text): """將字符串安全轉換為int類型,當int值小於1時,返回1""" result = to_int(text) # 判斷轉換后的結果值是否小於1,是的話返回1 if not result or result < 1: return 1 else: return result
大家可能會奇怪,為什么要增加這兩個多余的函數?事實上,這兩個函數使用頻率比前面那個會更高,因為我們在日常使用當中,經常會要求數值不能小於0或小於1,而to_int()函數轉換時,用戶如果輸入了負數,雖然轉換成功了,但這個值卻不是我們想要的結果,如果每次都要加上一段代碼對值進行判斷,那會更加麻煩,所以進行了再次封裝,多出來to_int0()和to_int()1兩個函數。
對這幾個函數我們用unittest測試一下,看看結果。
我們在test文件夾創建一個convert_helper_test.py文件,並編寫測試代碼,用來測試輸入各種值,看看是否得到我們期望的值。(PS:使用debug運行時,光標在那個函數中,unittest就會運行那個測試函數,所以如果有多個測試函數要運行時,最好用鼠標點擊一下main函數,即入口函數,再運行debug,這樣全部測試函數都會運行到)
#!/usr/bin/evn python # coding=utf-8 import datetime import unittest from common import convert_helper class ConvertHelperTest(unittest.TestCase): """轉換操作包測試類""" def setUp(self): """初始化測試環境""" print('------ini------') def tearDown(self): """清理測試環境""" print('------clear------') def test_to_int(self): self.assertEqual(convert_helper.to_int('1'), 1) self.assertEqual(convert_helper.to_int('1.0'), 0) self.assertEqual(convert_helper.to_int('1a'), 0) self.assertEqual(convert_helper.to_int('aaa'), 0) self.assertEqual(convert_helper.to_int(''), 0) self.assertEqual(convert_helper.to_int(None), 0) self.assertEqual(convert_helper.to_int('-1'), -1) self.assertEqual(convert_helper.to_int(10), 10) self.assertEqual(convert_helper.to_int(-10), -10) self.assertEqual(convert_helper.to_int0('1'), 1) self.assertEqual(convert_helper.to_int0('1.0'), 0) self.assertEqual(convert_helper.to_int0('1a'), 0) self.assertEqual(convert_helper.to_int0('aaa'), 0) self.assertEqual(convert_helper.to_int0(''), 0) self.assertEqual(convert_helper.to_int0(None), 0) self.assertEqual(convert_helper.to_int0('-1'), 0) self.assertEqual(convert_helper.to_int0(10), 10) self.assertEqual(convert_helper.to_int0(-10), 0) self.assertEqual(convert_helper.to_int1('1'), 1) self.assertEqual(convert_helper.to_int1('1.0'), 1) self.assertEqual(convert_helper.to_int1('1a'), 1) self.assertEqual(convert_helper.to_int1('aaa'), 1) self.assertEqual(convert_helper.to_int1(''), 1) self.assertEqual(convert_helper.to_int1(None), 1) self.assertEqual(convert_helper.to_int1('-1'), 1) self.assertEqual(convert_helper.to_int1(10), 10) self.assertEqual(convert_helper.to_int1(-10), 1) if __name__ == '__main__': unittest.main()
在這個單元測試中,我們使用的是python自帶的unittest這個模塊。
這里我們調用了unittest的斷言函數assertEqual(等於)來判斷convert_helper包的to_int()、to_int0()、to_int1()函數的執行結果是否和我們設定的值一致
通過測試可以看到,to_int系列函數的值是不一樣的:
輸入值 | 調用函數 to_int() |
調用函數 to_int0() |
調用函數 to_int1() |
非數值型字符串 | 0 | 0 | 1 |
-1 | -1 | 0 | 1 |
10 | 10 | 10 | 10 |
unittest還有很多其他斷言函數提供給我們使用,比如assertNotEqual(不等於)、assertGreaterEqual(大於等於)、assertGreater(大於)、assertAlmostEqual(約等於)、assertIsNotNone(不等於None)、assertIn(in)、assertNotIn(not in)、assertIs(is)、assertDictEqual(字典比較)、assertListEqual(列表比較)......還有好多其他類型的判斷處理。
使用單元測試除了上面所說的好處外,它還可以幫助我們實現自動化測試。比如說項目開發的過程中,有人修改了底層的這些工具函數,增加了新的判斷處理,這可能只是一個小小的修改,大家都覺得不會有什么問題,但有可能這點小改動會造成災難性的故障(我本人就試過,有些很小很小的改動,對多個合作客戶調用的接口測試過也沒有問題,可沒想到遺漏了另外一個客戶的測試,然后造成那個合作客戶的用戶訪問都出現異常,無法從我的系統中讀取到數據)。而有了這些已經實現了的自動化測試用例在,修改過或上線前,只需要簡單的點一下運行,就可以幫我們對所有函數都進行全面的測試,幫我們及時找到可能出現的Bug。
對於float類型數值和decimal類型數值,如果有需要,大家也可以自己去添加0或1最小值的判斷。
to_datetime()函數,會根據輸入的日期字符串格式,轉換成對應的日期(如:2017-09-01)、日期時間(2017-09-01 11:11)、日期時分秒(2017-09-01 11:11:11)、日期時分秒毫秒類型(2017-09-01 11:11:11.111),得到的值是datetime類型
當然也可以直接使用打印輸出結果的方式來進行測試,不過結果無法自動進行判斷是否是我們期望的值
def test_to_datetime(self): print('---test_to_datetime---') print(convert_helper.to_datetime(None)) print(convert_helper.to_datetime('')) print(convert_helper.to_datetime('xxx')) print(convert_helper.to_datetime('2017-09-01')) print(convert_helper.to_datetime('2017-09-01 11:11')) print(convert_helper.to_datetime('2017-09-0111:11')) print(convert_helper.to_datetime('2017-09-01 11:11:11')) print(convert_helper.to_datetime('2017-09-01 11:11:11.111'))
得到的結果是:
---test_to_datetime--- None None None 2017-09-01 00:00:00 2017-09-01 11:11:00 None 2017-09-01 11:11:11 2017-09-01 11:11:11.111000
對於日期類的測試如果使用斷言,我們通常要創建生成一個日期變量,然后在進行判斷
self.assertEqual(convert_helper.to_datetime(None), None) self.assertEqual(convert_helper.to_datetime(''), None) self.assertEqual(convert_helper.to_datetime('xxx'), None) result = datetime.datetime(2017, 9, 1) self.assertEqual(convert_helper.to_datetime('2017-09-01'), result) result = datetime.datetime(2017, 9, 1, 11, 11) self.assertEqual(convert_helper.to_datetime('2017-09-01 11:11'), result) self.assertEqual(convert_helper.to_datetime('2017-09-0111:11'), None) result = datetime.datetime(2017, 9, 1, 11, 11, 11) self.assertEqual(convert_helper.to_datetime('2017-09-01 11:11:11'), result) result = datetime.datetime(2017, 9, 1, 11, 11, 11, 111000) self.assertEqual(convert_helper.to_datetime('2017-09-01 11:11:11.111'), result)
to_date()函數是用來將各種格式的日期字符串,轉換為只含年月日(2017-09-01)的日期格式,具體大家使用代碼測試一下就知道了
to_timestamp10()函數是用來將各種格式的日期字符串,轉換為長度為10位長度的時間戳
to_timestamp13()函數是用來將各種格式的日期字符串,轉換為長度為13位長度的時間戳
具體這些測試例子,可下載文章后面的源碼包查看了解
下面我們來熟悉一下datetime_helper.py這個日期函數操作包,這個包里的函數類型主要有兩大類,一種是日期類型轉換,將日期類型格式化為字符串類型或轉換為數值類型;另一種是對日期類型的比較或運算。
先上代碼:

1 #!/usr/bin/evn python 2 # coding=utf-8 3 4 import time 5 import datetime 6 7 8 def to_date(dt): 9 """將時間格式化為日期字符串""" 10 if isinstance(dt, datetime.datetime): 11 return dt.strftime('%Y-%m-%d') 12 elif isinstance(dt, datetime.date): 13 return dt.strftime('%Y-%m-%d') 14 else: 15 raise Exception("日期類型錯誤") 16 17 18 def to_datetime(dt): 19 """將時間格式化為日期時間字符串""" 20 if isinstance(dt, datetime.datetime): 21 return dt.strftime('%Y-%m-%d %H:%M:%S') 22 elif isinstance(dt, datetime.date): 23 return dt.strftime('%Y-%m-%d') 24 else: 25 raise Exception("日期類型錯誤") 26 27 28 def to_number(): 29 """當前時間轉換為年月日時分秒毫秒共10位數的字符串""" 30 return datetime.datetime.now().strftime('%Y%m%d%H%M%S') 31 32 33 def to_timestamp10(): 34 """獲取當前時間長度為10位長度的時間戳""" 35 return int(time.time()) 36 37 38 def to_timestamp13(): 39 """獲取當前時間長度為13位長度的時間戳""" 40 return int(time.time() * 1000) 41 42 43 def timedelta(sign, dt, value): 44 """ 45 對指定時間進行加減運算,幾秒、幾分、幾小時、幾日、幾周、幾月、幾年 46 sign: y = 年, m = 月, w = 周, d = 日, h = 時, n = 分鍾, s = 秒 47 dt: 日期,只能是datetime或datetime.date類型 48 value: 加減的數值 49 return: 返回運算后的datetime類型值 50 """ 51 if not isinstance(dt, datetime.datetime) and not isinstance(dt, datetime.date): 52 raise Exception("日期類型錯誤") 53 54 if sign == 'y': 55 year = dt.year + value 56 if isinstance(dt, datetime.date): 57 return datetime.datetime(year, dt.month, dt.day) 58 elif isinstance(dt, datetime.datetime): 59 return datetime.datetime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond) 60 else: 61 return None 62 elif sign == 'm': 63 year = dt.year 64 month = dt.month + value 65 ### 如果月份加減后超出范圍,則需要計算一下,對年份進行處理 ### 66 # 如果月份加減后等於0時,需要特殊處理一下 67 if month == 0: 68 year = year - 1 69 month = 12 70 else: 71 # 對年月進行處理 72 year = year + month // 12 73 month = month % 12 74 if isinstance(dt, datetime.date): 75 return datetime.datetime(year, month, dt.day) 76 elif isinstance(dt, datetime.datetime): 77 return datetime.datetime(year, month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond) 78 else: 79 return None 80 elif sign == 'w': 81 delta = datetime.timedelta(weeks=value) 82 elif sign == 'd': 83 delta = datetime.timedelta(days=value) 84 elif sign == 'h': 85 delta = datetime.timedelta(hours=value) 86 elif sign == 'n': 87 delta = datetime.timedelta(minutes=value) 88 elif sign == 's': 89 delta = datetime.timedelta(seconds=value) 90 else: 91 return None 92 93 return dt + delta
to開頭的函數都是時間類型轉換函數(PS:convert_helper.py包里是對日期格式字符串轉為時間類型,而datetime_helper.py里所有操作,都是對時間類型進行處理的,將它們轉為其他格式)
比如to_date()和to_datetime(),這兩個函數分別是將時間類型格式化為年月日(2017-09-01)、年月日時分秒(2017-09-01 11:11:11)或數值字符串(20170901111111)
def to_date(dt): """將時間格式化為日期字符串""" if isinstance(dt, datetime.datetime): return dt.strftime('%Y-%m-%d') elif isinstance(dt, datetime.date): return dt.strftime('%Y-%m-%d') else: raise Exception("日期格式錯誤") def to_datetime(dt): """將時間格式化為日期時間字符串""" if isinstance(dt, datetime.datetime): return dt.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(dt, datetime.date): return dt.strftime('%Y-%m-%d') else: raise Exception("日期格式錯誤") def to_number(): """將當前時間轉換為年月日時分秒毫秒共14位數的字符串""" return datetime.datetime.now().strftime('%Y%m%d%H%M%S')
而to_timestamp10()和to_timestamp13()是獲取當前時間的時間戳
def to_timestamp10(): """獲取當前時間長度為10位長度的時間戳""" return int(time.time()) def to_timestamp13(): """獲取當前時間長度為13位長度的時間戳""" return int(time.time() * 1000)
對這種輸出類型的函數測試,我們測試時直接打印到控制台就可以了
在test文件夾中創建datetime_helper_test.py文件,然后通過打印來查看各函數會輸出什么值
#!/usr/bin/evn python # coding=utf-8 import datetime import unittest from common import datetime_helper class DatetimeHelperTest(unittest.TestCase): """日期函數操作包測試類""" def setUp(self): """初始化測試環境""" print('------ini------') def tearDown(self): """清理測試環境""" print('------clear------') def test(self): dt = datetime.datetime.now() print(datetime_helper.to_datetime(dt)) print(datetime_helper.to_date(dt)) print(datetime_helper.to_number()) print(datetime_helper.to_timestamp10()) print(datetime_helper.to_timestamp13()) if __name__ == '__main__': unittest.main()
運行后打印到控制台上的值:
------ini------ 2017-09-01 18:45:39 2017-09-01 20170901184539 1504262739 1504262739217 ------clear------

1 def timedelta(sign, dt, value): 2 """ 3 對指定時間進行加減運算,幾秒、幾分、幾小時、幾日、幾周、幾月、幾年 4 sign: y = 年, m = 月, w = 周, d = 日, h = 時, n = 分鍾, s = 秒 5 dt: 日期,只能是datetime或datetime.date類型 6 value: 加減的數值 7 return: 返回運算后的datetime類型值 8 """ 9 if not isinstance(dt, datetime.datetime) and not isinstance(dt, datetime.date): 10 raise Exception("日期類型錯誤") 11 12 if sign == 'y': 13 year = dt.year + value 14 if isinstance(dt, datetime.date): 15 return datetime.datetime(year, dt.month, dt.day) 16 elif isinstance(dt, datetime.datetime): 17 return datetime.datetime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond) 18 else: 19 return None 20 elif sign == 'm': 21 year = dt.year 22 month = dt.month + value 23 ### 如果月份加減后超出范圍,則需要計算一下,對年份進行處理 ### 24 # 如果月份加減后等於0時,需要特殊處理一下 25 if month == 0: 26 year = year - 1 27 month = 12 28 else: 29 # 對年月進行處理 30 year = year + month // 12 31 month = month % 12 32 if isinstance(dt, datetime.date): 33 return datetime.datetime(year, month, dt.day) 34 elif isinstance(dt, datetime.datetime): 35 return datetime.datetime(year, month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond) 36 else: 37 return None 38 elif sign == 'w': 39 delta = datetime.timedelta(weeks=value) 40 elif sign == 'd': 41 delta = datetime.timedelta(days=value) 42 elif sign == 'h': 43 delta = datetime.timedelta(hours=value) 44 elif sign == 'n': 45 delta = datetime.timedelta(minutes=value) 46 elif sign == 's': 47 delta = datetime.timedelta(seconds=value) 48 else: 49 return None 50 51 return dt + delta
timedelta()函數,它主要用於時間的加減運算,可以得出加減幾秒、幾分、幾小時、幾日、幾周、幾月、幾年后的時間值是什么,這個函數在實際開發中使用頻率還算是挺高的。
PS:原datetime.timedelta函數沒有對年和月的加減運算,對這個我進行了擴展,增加了年和月的加減計算
def test_timedelta(self): print('---test_timedelta---') result = datetime.datetime(2018, 9, 1) print(result) self.assertEqual(datetime_helper.timedelta('y', datetime.datetime(2017, 9, 1), 1), result) result = datetime.datetime(2016, 9, 1) print(result) self.assertEqual(datetime_helper.timedelta('y', datetime.datetime(2017, 9, 1), -1), result) result = datetime.datetime(2018, 3, 1) print(result) self.assertEqual(datetime_helper.timedelta('m', datetime.datetime(2017, 9, 1), 6), result) result = datetime.datetime(2017, 3, 1) print(result) self.assertEqual(datetime_helper.timedelta('m', datetime.datetime(2017, 9, 1), -6), result) result = datetime.datetime(2017, 3, 1) print(result) self.assertEqual(datetime_helper.timedelta('m', datetime.datetime(2017, 9, 1), -6), result) result = datetime.datetime(2017, 9, 8) print(result) self.assertEqual(datetime_helper.timedelta('w', datetime.datetime(2017, 9, 1), 1), result) result = datetime.datetime(2017, 8, 25) print(result) self.assertEqual(datetime_helper.timedelta('w', datetime.datetime(2017, 9, 1), -1), result) result = datetime.datetime(2017, 9, 2) print(result) self.assertEqual(datetime_helper.timedelta('d', datetime.datetime(2017, 9, 1), 1), result) result = datetime.datetime(2017, 8, 31) print(result) self.assertEqual(datetime_helper.timedelta('d', datetime.datetime(2017, 9, 1), -1), result) result = datetime.datetime(2017, 9, 1, 1) print(result) self.assertEqual(datetime_helper.timedelta('h', datetime.datetime(2017, 9, 1), 1), result) result = datetime.datetime(2017, 8, 31, 23) print(result) self.assertEqual(datetime_helper.timedelta('h', datetime.datetime(2017, 9, 1), -1), result) result = datetime.datetime(2017, 9, 1, 0, 1) print(result) self.assertEqual(datetime_helper.timedelta('n', datetime.datetime(2017, 9, 1), 1), result) result = datetime.datetime(2017, 8, 31, 23, 59) print(result) self.assertEqual(datetime_helper.timedelta('n', datetime.datetime(2017, 9, 1), -1), result) result = datetime.datetime(2017, 9, 1, 0, 0, 1) print(result) self.assertEqual(datetime_helper.timedelta('s', datetime.datetime(2017, 9, 1), 1), result) result = datetime.datetime(2017, 8, 31, 23, 59, 59) print(result) self.assertEqual(datetime_helper.timedelta('s', datetime.datetime(2017, 9, 1), -1), result)
運行后打印到控制台上的值:
------ini------ ---test_timedelta--- 2018-09-01 00:00:00 2016-09-01 00:00:00 2018-03-01 00:00:00 2017-03-01 00:00:00 2017-03-01 00:00:00 2017-09-08 00:00:00 2017-08-25 00:00:00 2017-09-02 00:00:00 2017-08-31 00:00:00 2017-09-01 01:00:00 2017-08-31 23:00:00 2017-09-01 00:01:00 2017-08-31 23:59:00 2017-09-01 00:00:01 2017-08-31 23:59:59 ------clear------
版權聲明:本文原創發表於 博客園,作者為 AllEmpty 本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。
python開發QQ群:669058475(本群已滿)、733466321(可以加2群) 作者博客:http://www.cnblogs.com/EmptyFS/