python之路-day19-面向對象之約束

1、上次內容回顧java

 

一、反射python

  一、hasattr(對象,屬性(字符串))c#

  二、getattr(對象,屬性(字符串))app

  三、setattr(對象,屬性,值)ide

  四、delattr(對象,屬性)函數

 

二、issubclass ,type , isinstancespa

  issunclass,判斷xxx對象或者類是不是xxx的子類debug

  type:獲取xxx對象的數據類型日誌

  isinstance:判斷xxx對象是不是xxx類型(向上查找)code

 

三、方法和

  類外面寫的函數都是函數

  在類中:

    實例方法:

      一、類名.方法()  函數

      二、對象.方法()  方法

    類方法:

      都是方法

    靜態方法

      都是函數

四、md5

  特色:不可逆

  加鹽

  import hashlib

  obj = hashlib.md5(鹽)

  obj.update(byte類型的明文)

  result = obj.hetdidest()

 

2、類的約束
類的約束,主要是爲了定義一個父類,約束下面子類必須按照規則
完成父類中的功能(父類中的功能爲空白)
在python中有兩種辦法來解決這樣的問題
一、提取父類。而後再父類中定義好方法。在這個方法中什麼都不用幹,拋一個異常
就能夠了。這樣全部的子類都必須重寫這個方法。不然,訪問的時候報錯
二、使用元類來描述父類。在元類中給出一個抽象方法。這樣子類就不得不給出抽象方法
的具體實現。也能夠起到約束的效果

第一套方案示例:

class Base:
    def login(self):
        raise Exception("你沒有實現login⽅法()")
class Normal(Base):
    def login(self):
        pass
class Member(Base):
    def denglu(self):
        pass
class Admin(Base):
    def login(self):
        pass
# 項⽬經理寫的總⼊⼝
def login(obj):
    print("準備驗證碼.......")
    obj.login()
    print("進⼊主⻚.......")
n = Normal()
m = Member()
a = Admin()
login(n)
login(m) # 報錯.
login(a)

 

 
  在執行到login(m)那一步程序報錯,緣由是該類沒有login方法,致使去
訪問父類的login方法,拋出異常報錯
Exception異常,是全部異常的根。咱們沒法經過這個異常來判斷出程序
是由於什麼報的錯。因此,最好是換一個比較專業的錯誤信息,換成NotlmplementError
意爲:沒實現的錯誤
 
第二套方案:寫抽象類和抽象方法
from abc import ABCMeta, abstractmethod
# 類中包含了抽象⽅法. 那此時這個類就是個抽象類. 注意: 抽象類能夠有普通⽅法
class IGame(metaclass=ABCMeta):
    # ⼀個遊戲到底怎麼玩⼉? 你能形容? 流程能⼀樣麼?
    @abstractmethod
    def play(self):
        pass
    def turn_off(self):
        print("破B遊戲不玩了, 脫坑了")
class DNFGame(IGame):
    # ⼦類必須實現⽗類中的抽象⽅法. 不然⼦類也是抽象類
    def play(self):
        print("dnf的玩⼉法")
# g = IGame() # 抽象類不能建立對象
dg = DNFGame()
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 login(obj):
    print("準備驗證碼.......")
    obj.login()
    print("進⼊主⻚.......")

n = Normal()
m = Member()
a = Admin()
login(n)
login(m)
login(a)

 

 

 
總結: 約束. 其實就是⽗類對⼦類進⾏約束. ⼦類必需要寫xxx⽅法. 在python中約束的
⽅式和⽅法有兩種:
1. 使⽤抽象類和抽象⽅法, 因爲該⽅案來源是java和c#. 因此使⽤頻率仍是不多的
2. 使⽤⼈爲拋出異常的⽅案. 而且儘可能拋出的是NotImplementError. 這樣比較專
業, ⽽且錯誤比較明確.(推薦)
 
 
3、異常處理

上來先製造個異常:

def chu(a, b):
    return a/b
ret = chu(10, 0)
print(ret)

結果:
Traceback (most recent call last):
 File "/Users/sylar/PycharmProjects/oldboy/⾯向對象/day05.py", line 100, in
<module>
 ret = chu(10, 0)
 File "/Users/sylar/PycharmProjects/oldboy/⾯向對象/day05.py", line 98, in
chu
 return a/b
ZeroDivisionError: division by zero

      什麼錯誤呢. 除法中除數不能是0. 那若是真的出了這個錯. 你把這⼀堆信息拋給客戶
    麼? 確定不能. 那如何處理呢?

def chu(a, b):
    return a/b
try:
    ret = chu(10, 0)
    print(ret)
except Exception as e:
    print("除數不能是0")

結果:
除數不能是0
那try...except是什麼意思呢? 嘗試着運⾏xxxxx代碼. 出現了錯誤. 就執⾏except後⾯的
代碼. 在這個過程當中. 當代碼出現錯誤的時候. 系統會產⽣⼀個異常對象. 而後這個異常會向
外拋. 被except攔截. 並把接收到的異常對象賦值給e. 那這⾥的e就是異常對象. 那這⾥的
Exception是什麼? Exception是全部異常的基類, 也就是異常的跟. 換句話說. 全部的錯誤都
是Exception的⼦類對象. 咱們看到的ZeroDivisionError 其實就是Exception的⼦類. 那這樣
寫好像有點⼉問題撒. Exception表示全部的錯誤. 太籠統了. 全部的錯誤都會被認爲是Exception.
當程序中出現多種錯誤的時候, 就很差分類了, 最好是出什麼異常就⽤什麼來處理. 這樣就更加合理了.
因此在try...execpt語句中. 還能夠寫更多的except
import traceback
# 計算a+b
def cul(a, b):
    if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
        return a + b
    else:
        # 在這裏有兩種方案. 1. 直接返回 , 2. 拋出異常
        # raise 拋出 Exception 錯誤和異常,全部錯誤的根
        raise Exception("我要的不是這個. 你應該我傳遞int或者float")


try:
    print(cul(1, "胡辣湯")) # 加上異常的處理
except Exception as e:
    # 獲取到錯誤信息. 咱們須要訪問堆棧信息
    print(traceback.format_exc()) # 獲取堆棧信息
    print("出現了錯誤")


咱們出現的錯誤. python中沒有給出具體的記錄, 慎用. 名字必定要符合規範
JackException 一個讓人無從得知的自定義異常,切記慎用自定義異常
自定義異常
class GenderException(Exception):
    pass

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    #  洗澡 -> 男的進男浴室
    def goto_nan_yushi(self):
        if self.gender != "":
            raise GenderException("性別不對") # 除了名字之外都是父類中的Exception
        else:
            print("歡迎光臨.")
try:
    p2 = Person("wusir", "")
    p2.goto_nan_yushi()
    p1 = Person("alex", "")
    p1.goto_nan_yushi()
except GenderException as e:
    print("你去男澡堂子幹嗎?")
except Exception as e:
    print("其餘錯誤")

 

 
 
4、日誌處理
import logging
# filename: ⽂件名
# format: 數據的格式化輸出. 最終在⽇志⽂件中的樣⼦
# 時間-名稱-級別-模塊: 錯誤信息
# datefmt: 時間的格式
# level: 錯誤的級別權重, 當錯誤的級別權重⼤於等於leval的時候纔會寫⼊⽂件
logging.basicConfig(filename='x1.log',
     format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
     datefmt='%Y-%m-%d %H:%M:%S',
level=30)
# 當前配置表示 0以上的分數會被寫⼊⽂件
# CRITICAL = 50
# FATAL = CRITICAL
# ERROR = 40
# WARNING = 30
# WARN = WARNING
# INFO = 20
# DEBUG = 10
# NOTSET = 0
logging.critical("我是critical") # 50分. 最貴的
logging.error("我是error") # 40分
logging.warning("我是warning")
logging.info("我是info")
logging.debug("我是debug")
logging.log(1, "我什麼都不是")

import traceback
try:
    print(1/0)
except Exception:
    logging.error(traceback.format_exc()) # 用法
    print("出錯了")



import logging
# 建立⼀個操做⽇志的對象logger(依賴FileHandler)
#                       open()
file_handler = logging.FileHandler('zuo.log', 'a', encoding='utf-8')
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
logger1 = logging.Logger('qq', level=20)
logger1.addHandler(file_handler) # 把文件助手和日誌對象綁定
logger1.error('我是A系統出錯了') # 記錄日誌


# 再建立⼀個操做⽇志的對象logger(依賴FileHandler)
file_handler2 = logging.FileHandler('you.log', 'a', encoding='utf-8')
file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
logger2 = logging.Logger('B系統', level=20)
logger2.addHandler(file_handler2)


import traceback
try:
    print(1/0)
except Exception:
    logger2.critical(traceback.format_exc())
    print("出錯了. 請聯繫管理員")
print("程序繼續知悉個")




from types import MethodType, FunctionType
class Foo:
    @classmethod
    def func1(self):
        pass
    @staticmethod
    def func2(self):
        pass
    def func3(self):
        pass

    def func4(self):
        pass

obj = Foo()
lst.append(obj.func4)
for item in lst:
    print(isinstance(item, MethodType))
相關文章
相關標籤/搜索