類的約束 和 異常處理

本節主要內容: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
View Code

 

  而後呢,他們把代碼交給你了,你看了一眼,張三和王五還算ok,這個李四寫的什麼鬼啊?denglu....函數

難受不??可是好歹能用,還能湊活,可是這時你這邊要使用了,問題就來了測試

1 # 項目經理的入口
2 
3 def login(obj):
4     print("準備驗證碼.....")
5     obj.login()
6     print("進入主頁........")
View Code

  對於張三和王五的代碼,沒有問題,可是李四,你是否是調用不了,那如何避免這樣的問題呢?咱們要約束程序的結構,也就是說,在分配任務以前就應該把功能定義好,而後分別交給下面的程序員來完成相應的功能

  在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)
View Code

  在執行 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)
View Code

 

 

  總結:約束,其實就是父類對子類進行的約束,子類必需要按照父類的要求 寫 xx方法,在python中 約束的方式有兩種:

  1.使用抽象類和抽象方法,因爲該方案來源是 java 和 c# ,因此使用頻率仍是不多的

  2.使用人爲拋出異常的方案,而且儘可能拋出的是 NotlmplementError,這樣比較專業,並且錯誤比較明顯

 

二 異常處理

  首先咱們說一下,什麼是異常, 異常 是程序在運行過程當中產生的錯誤,就比如,你在回家的路上忽然天塌了,那這個屬於一個異常,總之就是不正常,那若是程序出現了異常,怎麼處理呢?

  咱們先製造一個錯誤,來看看異常長什麼樣

 

 

def chu(a,b):
    return a/b

ret = chu(10,0)
print(ret)
# 結果:
# ZeroDivisionError: division by zero
View Code

 

 

   什麼錯誤呢?除法中除數不能爲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
View Code

 

 

 

  那麼 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("其餘錯誤")
View Code

 

  此時,程序運行過程當中,若是出現了ZeroDivisionError 就會被第一個 except 捕獲,若是出現了FileNotFountError 就會被第二個 except 捕獲,若是都不是這鏈各個異常,那就會被最後的 Exception  捕獲,總之最後的 Exception 就是咱們處理 異常的最後一道防衛,這是咱們 最經常使用的一套寫法, 接下來看一套最完整的 異常處理寫法(語法):

try:
    """ 操做"""
except Exception as e:
    """ 異常的父類,能夠捕獲全部的異常..."""
else:
    """保護不拋出異常的代碼,當try 中 無異常的時候執行..."""
finally:
    """最後老是要執行我...."""
View Code

  解讀:程序先執行操做,而後若是出錯了會走 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("報錯了,你本身看着辦吧")
View Code

  當程序運行到 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("反正報錯了")
View Code

    搞定了,可是,若是是真的報錯了,咱們在測試的時候,最好是能看到錯誤源於哪裏,怎麼辦呢? 須要引入一個模塊, 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: 性別不對,別進了
View Code

  搞定了,這樣咱們就能收放自如了,當測試代碼的時候吧 堆棧信息打印出來,可是當到了線上的生產環境的時候把這個堆棧去掉便可

 

四 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)
# 如今能夠了,不會再擔憂 撞庫了
View Code

  那 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("失敗")
View Code

  因此,之後存密碼就不要存明文了,要存密文,安全,而且,這裏的加鹽不能改來改去的 ,不然,整套密碼就都亂了

相關文章
相關標籤/搜索