本節主要內容:java
1.類的約束python
2.異常處理程序員
3.自定義異常算法
4.MD5 加密數據庫
5.日誌c#
一 類的約束安全
首先,你要清楚,約束是對類的越是,好比,你是一個項目經理,而後呢,你給手下的人分活,張三,你處理一下普通用戶登陸,李四,你處理一下會員登陸,王五,你處理一下管理員登陸,那這個時候呢,他們就開始分別去寫他們的功能了,可是呢,你要知道,程序員不必定會有那麼好的默契,頗有可能三個程序員會寫三個徹底不一樣的方法,好比這樣:ide
1 class Normal: # 張三,普通會員登陸 2 def login(self): 3 pass 4 5 class Member: # 李四,會員登陸 6 def denglu(self): 7 pass 8 9 class Admin: # 王五,管理員登陸 10 def login(self): 11 pass
而後呢,他們把代碼交給你了,你看了一眼,張三和王五還算ok,這個李四寫的什麼鬼啊?denglu....函數
難受不??可是好歹能用,還能湊活,可是這時你這邊要使用了,問題就來了測試
1 # 項目經理的入口 2 3 def login(obj): 4 print("準備驗證碼.....") 5 obj.login() 6 print("進入主頁........")
對於張三和王五的代碼,沒有問題,可是李四,你是否是調用不了,那如何避免這樣的問題呢?咱們要約束程序的結構,也就是說,在分配任務以前就應該把功能定義好,而後分別交給下面的程序員來完成相應的功能
在python 中有兩種辦法來解決這樣的問題
1.提取父類,而後在父類中定義好方法,在這個方法中什麼都不用幹,就拋一個異常就能夠了,這樣全部的子類就必須重寫這個方法,不然,訪問的時候就會報錯
2.使用元類來描述父類,在元類中給出一個抽象方法,這樣子類就不得不給出抽象方法的具體實現,也能夠獲得約束的效果
首先,咱們先看一種解決方案,首先,提取一個父類,在父類中給出一個方法,而且在方法中不給出任何代碼,直接拋異常
1 class Base: 2 def login(self): 3 raise Exception("你沒有實現方法login()") 4 class Normal(Base): 5 def login(self): 6 pass 7 8 class Member(Base): 9 def denglu(self): 10 pass 11 12 class Admin(Base): 13 def login(self): 14 pass 15 16 # 項目經理的入口 17 def login(obj): 18 print("準備驗證碼.....") 19 obj.login() 20 print("進入主頁........") 21 22 n = Normal() 23 m = Member() 24 a = Admin() 25 login(n) 26 login(m) # 報錯 Exception: 你沒有實現方法login() 27 login(a)
在執行 login(m)的時候程序會報錯,緣由是,此時訪問的 login() 是父類總的方法,可是富尅 的方法會拋出一個異常,因此報錯,這樣程序員就不得不寫 login方法了,從而對子類進行了相應的約束
在本例中,要注意,咱們拋出的是 Exception 異常,而 Exception 是全部異常的根,咱們沒法經過這個異常來判斷出程序 是由於什麼報的錯,因此,最好是換一個 專業的錯誤信息,最好是換成 NotlmplementError
其含義是"沒有實現的錯誤" 這樣程序員 或者 項目經理 能夠一目瞭然的知道是什麼錯了,就比如,你犯什麼錯了,你也不知道哪裏錯了,這時我告訴你,你xx 錯了,你改也知道改哪不是?
第二套方案,寫抽象類 和抽象方法,這種方案相對於上一種方案來講麻煩一些,須要先引入一個抽象的概念,什麼是抽象呢?這裏動物的吃就是一個抽象的概念,只是一個動做的概念,沒有具體實現,這就是抽象的動做,換句話說,咱們若是寫一個方法,不知道方法的內部應該到底怎麼寫,那這個方法其實就應該是一個抽象的方法,若是一個類中包含抽象方法,那麼這個類必定是一個抽象類,抽象類是不能有實例的,好比,你看看一些抽象派的畫做,在現實中是不存在的,也就沒法創建實例對象與之相對應,因此抽象類沒法建立對象,建立對象的時候會報錯.
在 python 中編寫一個抽象類比較麻煩,須要 引入 abc 模塊中的 ABCMeta 和 abstractmethod 這兩個內容,來看一個例子
1 from abc import ABCMeta,abstractmethod 2 3 # 類中包含了抽象方法,那此時這個類就是個抽象類,注意:抽象類能夠有普通方法 4 class IGame(metaclass=ABCMeta): 5 # 一個遊戲到底怎麼玩兒?你能形容?路程能同樣麼? 6 @abstractmethod 7 def play(self): 8 pass 9 10 def turn_off(self): 11 print("破遊戲不玩了,脫坑了") 12 13 class DNFGame(IGame): 14 # 子類必須實現父類中的抽象方法,不然子類也是 抽象類 15 16 def play(self): 17 print("dnf 的玩兒法") 18 19 # g = IGame() # 抽象類不能建立對象 20 21 dg = DNFGame() 22 dg.play()
經過代碼咱們發現這裏的 IGame 對 DNFGame 進行了約束,換句話說,父類對子類進行了約束
from abc import ABCMeta,abstractmethod class Base(metaclass=ABCMeta): @abstractmethod def login(self): pass class Normal(Base): def login(self): pass class Member(Base): def denglu(self): # 這個沒用了 pass def login(self): # 子類對 父類 進行 實現 pass class Admin(Base): def login(self): pass # 項目經理入口 def func(obj): print("準備驗證碼...") obj.login() print("進入主頁.....") n = Normal() m = Member() a = Admin() func(n) func(m) func(a)
總結:約束,其實就是父類對子類進行的約束,子類必需要按照父類的要求 寫 xx方法,在python中 約束的方式有兩種:
1.使用抽象類和抽象方法,因爲該方案來源是 java 和 c# ,因此使用頻率仍是不多的
2.使用人爲拋出異常的方案,而且儘可能拋出的是 NotlmplementError,這樣比較專業,並且錯誤比較明顯
二 異常處理
首先咱們說一下,什麼是異常, 異常 是程序在運行過程當中產生的錯誤,就比如,你在回家的路上忽然天塌了,那這個屬於一個異常,總之就是不正常,那若是程序出現了異常,怎麼處理呢?
咱們先製造一個錯誤,來看看異常長什麼樣
def chu(a,b): return a/b ret = chu(10,0) print(ret) # 結果: # ZeroDivisionError: division by zero
什麼錯誤呢?除法中除數不能爲0,那若是真的出了這個錯,你把這一對錯誤拋給使用者嘛? 確定不能啊
那如何處理呢???
def chu(a,b): return a/b try: ret = chu(10,0) print(ret) except Exception as e: print(e) print("除數不能爲0") # 結果: # division by zero # 除數不能爲0
那麼 try ....except 是什麼意思呢?嘗試着運行 xxxx代碼,出現了錯誤,就執行 except 後面的代碼,在這個過程當中,當代碼出現錯誤的時候,系統會產生一個異常對象,而後這個異常 會向外拋,被 except 攔截, 並把接收到的異常對象 賦值給 e,那這裏的 e 就是異常對象, 那這裏的 Exception 是什麼呢? Exception 是全部的異常的 基類(父類) ,也就是異常的根,換句話說,全部的錯誤都是 Exception 的子類,那這樣寫 好像有點問題啊, Exception 表示全部的錯誤,太籠統了,全部的錯誤都會被認爲是 Exception,當程序出 多種錯誤的時候,就很差分類了,組好事什麼異常就用什麼處理,這樣就更加合理了,因此在 try...except 語句彙總,還能夠寫入更多的 except
try: print("各類操做...") except ZeroDivisionError as e: print("除數不能爲0") except FileNotFoundError as e: print("文件不存在...") except Exception as e: print("其餘錯誤")
此時,程序運行過程當中,若是出現了ZeroDivisionError 就會被第一個 except 捕獲,若是出現了FileNotFountError 就會被第二個 except 捕獲,若是都不是這鏈各個異常,那就會被最後的 Exception 捕獲,總之最後的 Exception 就是咱們處理 異常的最後一道防衛,這是咱們 最經常使用的一套寫法, 接下來看一套最完整的 異常處理寫法(語法):
try: """ 操做""" except Exception as e: """ 異常的父類,能夠捕獲全部的異常...""" else: """保護不拋出異常的代碼,當try 中 無異常的時候執行...""" finally: """最後老是要執行我...."""
解讀:程序先執行操做,而後若是出錯了會走 except的代碼,若是不出錯,這行else 中的代碼,不論出不出錯,最後都要執行 finally 中的 語句, 通常咱們 用 try...except 就夠了,頂多加上 finally ,finally 通常用來做爲收尾工做
上面是處理異常,咱們在執行代碼的過程當中若是出現了一些條件上的不對等,根本不符合個人代碼邏輯,好比,參數,我要求你傳遞一個數字,你非傳遞一個字符串,那 "對不起,我是 警察" 哈哈哈....... 這樣的我是沒辦法處理的,那如何通知你呢? 兩個 方案:
1.方案1: 直接返回便可,我無論你
2.方案2: 拋出一個異常,告訴你,我很差惹,乖乖的聽話
第一種方案是咱們以前寫代碼常常用到的方案,但這種方案並不夠好,沒法起到警示做用,因此,之後的代碼中出現了相似的問題,直接拋出一個錯誤,那怎麼拋呢? 咱們要用到 raise 關鍵字
def add(a,b): """ 給我傳遞兩個參數,我幫你計算這兩個數的和 :param a: :param b: :return: """ if not type(a) == int and type(b) == int: """ 當程序運行到這句話的時候,整個函數的調用會中斷,拋出一個異常""" raise Exception("不是整數,臣妾作不到啊") return a + b # 若是調用方不處理異常,那產生的錯誤將會繼續往外拋,最後就拋給了使用者 # add("你好,我叫 張曼玉") # 若是 調用方吹了異常,那麼錯誤就不會 拋給使用者,程序也能正常運行 try: add("我是至尊寶","你是紫霞仙子嘛?") except Exception as e: print("報錯了,你本身看着辦吧")
當程序運行到 raise 的時候, 程序會被中斷,並實例化後面的異常對象,拋給調用方,若是調用方不處理,則會把錯誤繼續向上拋出,最後拋給 使用者,若是調用方處理了異常,那程序能夠正常運行了
說了這麼多,異常也知道如何拋出 和 處理了,可是如今咱們用的都是 python 自帶 的異常,若是有一天,你本身寫的代碼中 出現了 一個 沒法用現有的 異常來解決,那怎麼辦? 試試,能不能 ,自定義一個??/
其實 自定義一個 也很簡單,只要你的類繼承 了 Exception 類,那你的類就是一個 異常類,就這麼簡單.
# 繼承 Exception ,那這個類就是一個 異常類 class GenderError(Exception): pass class Person: def __init__(self,name,gender): self.name = name self.gender = gender def men_bathroom(person): if person.gender != "男": raise GenderError("性別不對,這裏是男澡堂") p1 = Person("哈哈哥","男") p2 = Person("嘻嘻姐","我不知道") # men_bathroom(p1) # men_bathroom(p2) # 會拋出一個異常 GenderError # 處理異常 try: men_bathroom(p1) men_bathroom(p2) except GenderError as e: print(e) # 性別不對,這裏是男澡堂 except Exception as e: print("反正報錯了")
搞定了,可是,若是是真的報錯了,咱們在測試的時候,最好是能看到錯誤源於哪裏,怎麼辦呢? 須要引入一個模塊, traceback,這個模塊能夠獲取到咱們每一個方法的調用信息,有被稱爲堆棧信息,這個信息對咱們排錯頗有幫助的
import traceback # 繼承 Exception,那這個類 就是一個 異常類 class GenderError(Exception): pass class Person: def __init__(self,name,gender): self.name = name self.gender = gender def men_bathroom(person): if person.gender != "男": raise GenderError("性別不對,別進了") p1 = Person("哈哈哥","男") p2 = Person("嘻嘻姐","不知道哎") try: men_bathroom(p1) men_bathroom(p2) except GenderError as e: val = traceback.format_exc() # 獲取到堆棧信息 print(e) # 性別不對,別進了 print(val) except Exception as e: print("反正錯了") # 結果 # 性別不對,別進了 # raise GenderError("性別不對,別進了") # GenderError: 性別不對,別進了
搞定了,這樣咱們就能收放自如了,當測試代碼的時候吧 堆棧信息打印出來,可是當到了線上的生產環境的時候把這個堆棧去掉便可
四 MD5加密
想一個事情. 你在銀行取錢或者辦卡的時候. 咱們都要輸入密碼. 那這個密碼若是就按照咱們輸入的那樣去存儲. 是否是很不安全啊. 若是某一個程序員進入到了了銀行的數據庫. 而銀行的數據庫又存的都是明文(不加密的密碼)密碼. 這時, 整個銀行的帳戶里的信息都是很是不安全的. 那怎麼辦才安全呢? 給密碼加密. 而且是不可逆的加密算法. 這樣. 即便獲取到了銀行的帳戶和密碼信息. 對於黑客而言都沒法進行破解. 那咱們的帳號就相對安全了了不少. 那怎麼加密呢? 最多見的就是用MD5算法.
MD5是一種不可逆的加密算法. 它是可靠的. 而且安全的. 在python中咱們不須要手寫
這一套算法. 只須要引入⼀個叫 hashlib 的模塊就能搞定MD5的加密工做
import hashlib obj = hashlib.md5() obj.update("哈哈哥".encode("utf-8")) # 加密的必須是字節 miwen = obj.hexdigest() print(miwen) # 若是擔憂被破解,也就是 撞庫,能夠加鹽,對沒錯,就是 加鹽 import hashlib obj = hashlib.md5(b"saddfgflhmdlfmdas") # 加鹽 obj.update("alex".encode("utf-8")) miwen = obj.hexdigest() print(miwen) # 如今能夠了,不會再擔憂 撞庫了
那 MD5 怎麼用呢??
import hashlib def my_md5(s): obj = hashlib.md5() obj.update(s.encode("utf-8")) miwen = obj.hexdigest() return miwen username = input("輸入用戶名:") password = input("輸入密碼:") # 數據存儲 的時候: # username:my_md5(password) # 假設如今的用戶名 和 密碼分別是 # hahage:b3ed7cbc208610c252e2ea825c5f31e5 # 123456:e10adc3949ba59abbe56e057f20f883e # print(my_md5(username)) # print(my_md5(password)) # 用戶登陸 if my_md5(username) == "b3ed7cbc208610c252e2ea825c5f31e5" and \ my_md5(password) == "e10adc3949ba59abbe56e057f20f883e": print("成功") else: print("失敗")
因此,之後存密碼就不要存明文了,要存密文,安全,而且,這裏的加鹽不能改來改去的 ,不然,整套密碼就都亂了