python面向?qū)ο?/strong>
2019-06-01
--張伯羽
1.單例模式
單例模式的主要目的是確保某一個類只有一個實(shí)例存在
- 例子:
class DB:
instance = None
def __new__(cls, *args, **kwargs):
if DB.instance is None:
DB.instance = super().__new__(cls)
return DB.instance
# 每次都只會生成一個實(shí)例
2.MVC:模型——視圖——控制器 框架
- 模型(Model)
模型是核心部分,包含和管理業(yè)務(wù)邏輯、數(shù)據(jù)、狀態(tài)和應(yīng)用規(guī)則,模型執(zhí)行所有的狀態(tài)改變和必要的校驗(yàn),并告訴控制器該做什么
- 視圖
視圖不負(fù)責(zé)處理數(shù)據(jù),只展示數(shù)據(jù),是數(shù)據(jù)可視化的表現(xiàn),窗口、pdf文檔、應(yīng)用圖形界面等都是視圖
- 控制器
控制器控制視圖和模型的通信,與模型交互,按照模型的指令控制視圖
3.觀察者設(shè)計模式
又名:發(fā)布-訂閱模式、模型-視圖模式、源-監(jiān)聽器模式以及從屬者模式
- 借鑒一些人的說法,在打游戲時,你撿到了一把AWM,接著便向隊(duì)友喊話炫耀,這時與你連麥的隊(duì)友都能聽到你的喊話并跑過來把你打死,再搶走那把AWM......
- 又例如,當(dāng)訂閱者訂閱了某系列雜志,當(dāng)雜志有了新的狀態(tài),比如更新了,那么此時就會給所有的訂閱者發(fā)送一條消息,那么所有的訂閱者就會收到此消息做出購買或不購買的選擇。
- 或是產(chǎn)品中介會聯(lián)系賣家和買家,向賣家和買家提供最新消息。
-
Subject(觀察者集合)
class Subject:
def __init__(self):
self.observers = []
def add_observer(self, observer):
self.observers.append(observer)
return self
def remove_observer(self, observer):
self.observers.remove(observer)
def notify(self, msg):
for observer in self.observers:
observer.update(msg)
Subject可以包含多個觀察者對象并對這些觀察者進(jìn)行管理,比如添加add_oberver(...)、移除remove_observer(...)和發(fā)送通知給所有觀察者notify(...)
2.Observer(抽象觀察者)
包含觀察者應(yīng)該具有的屬性和接受信息(更新數(shù)據(jù))的方法,觀察者對觀察目標(biāo)的變化做出反應(yīng)
3.ConcreteSubject(目標(biāo)狀態(tài))
它改變時便會通知觀察者集合
4.ConcreteObserver(具體觀察者)
具體觀察者中會維護(hù)一個指向具體目標(biāo)對象的引用,它存儲了具體觀察者的狀態(tài),這些狀態(tài)和具體目標(biāo)的狀態(tài)要保持一致。
它實(shí)現(xiàn)了抽象觀察者對象的updata方法,并且可以把自己加入到觀察者集合中
class Observer:
def __init__(self, name):
self.name = name
def update(self, msg):
print(self.name + "收到信息" + msg)
- 例子
xiaoming = Observer("xiaoming")
lihua = Observer("lihua")
rain = Subject()
rain.add_observer(xiaoming).add_observer(lihua)
rain.notify("xswl")
xiaoming收到信息xswl
lihua收到信息xswl
4.異常處理
- 獲得原諒比請求許可跟容易
- 異常發(fā)生后,程序就結(jié)束了
opt = int(input("請輸入一個整數(shù)"))
print(opt)
# 輸入‘d’異常
請輸入一個整數(shù)d
Traceback (most recent call last):
File "C:/Users/admin/PycharmProjects/監(jiān)控/異常處理.py", line 11, in <module>
opt = int(input("請輸入一個整數(shù)"))
ValueError: invalid literal for int() with base 10: 'd'
-
用try語句
# try:
# 可能發(fā)生異常的代碼
# except:
# 異常處理代碼
- except:處理所有異常
- except Type: 處理指定類型的異常
- except Type as data: 獲取異常信息
- except (Type1, Type2, Type3): 同時處理這三種異常,如果想獲得異常數(shù)據(jù),同樣可以使用as語句
# 輸入‘d’異常
請輸入一個整數(shù)d
Traceback (most recent call last):
File "C:/Users/admin/PycharmProjects/監(jiān)控/異常處理.py", line 30, in <module>
你輸入的不是一個數(shù)
# try:
# pass
# except 異常類型1:
# pass
# except 異常類型2:
# pass
# except (異常類型3, 異常類型4, 異常類型5):
# pass
# except Exception as e:
# print(e)
# 定義這種方式捕捉異常時,一定要先寫具體的異常,再寫具有普遍性的異常,所有的異常,繼承自Exception
-
else、finally
else是沒有發(fā)生異常時執(zhí)行
finally最終都會執(zhí)行
# try:
# pass
# except(valueError, KeyError):
# 發(fā)生異常時執(zhí)行
# else:
# 沒有發(fā)生異常時執(zhí)行
# finally:
# 有沒有異常都會執(zhí)行(一般用來釋放資源)
# try:
# print("zs")
# finally:
# print("finally")
try:
num = int(input("請輸入整數(shù)"))
result = 8/num
print(result)
except ValueError:
print("請輸入一個整數(shù)")
except ZeroDivisionError:
print("除數(shù)不能為0")
except Exception as e:
print("未知錯誤%s"% e)
else:
print("執(zhí)行正常")
finally:
print("執(zhí)行完成")
- 輸入不是整數(shù)異常:
# 輸入‘d’
請輸入整數(shù)d
請輸入一個整數(shù)
執(zhí)行完成
- 輸入除數(shù)為0:
# 輸入除數(shù)為0
請輸入整數(shù)0
除數(shù)不能為0
執(zhí)行完成
- 無異常:
請輸入整數(shù)3
2.6666666666666665
執(zhí)行正常
執(zhí)行完成
-
異常的傳遞
異常發(fā)生后,會傳遞給方法(函數(shù))的調(diào)用者A,如果A捕捉到該異常,則按捕捉機(jī)制處理,如果A沒有捕捉該異常,則會層層向上傳遞
最終會傳遞到python解析器,就簡單地中止程序
def fun1():
a = 0
print(10/a)
def fun2():
try:
fun1()
except ZeroDivisionError:
print("除數(shù)為0")
fun2()
除數(shù)為0
-
手動拋出異常:raise
def fun3():
print("hello")
raise ZeroDivisionError()
fun3()
Traceback (most recent call last):
File "C:/Users/admin/PycharmProjects/監(jiān)控/異常處理.py", line 90, in <module>
fun3()
hello
File "C:/Users/admin/PycharmProjects/監(jiān)控/異常處理.py", line 89, in fun3
raise ZeroDivisionError()
ZeroDivisionError
-
自定義異常(簡化程序)
將不符合條件的作為異常丟掉,從而簡化程序
如下例中“zhan”不符合用戶名條件,故執(zhí)行異常操作
class ParamInvalidException(Exception):# 繼承Exception類
def __init__(self, code, msg):
self.code = code
self.msg = msg
def login(username, pwd):
if len(username) < 6:
raise ParamInvalidException(2001, "用戶名長度在1~6之間")
if username != "zhangsan":
raise ParamInvalidException(2002, "用戶名錯誤")
print("登錄成功")
try:
# “zhan”不符合用戶名條件,故執(zhí)行異常操作
login("zhan", "12345")
print("后繼操作")
except ParamInvalidException as e:
print(e.code, e.msg)
2001 用戶名長度在1~6之間
-
程序發(fā)生異常該怎么辦
首先判斷是否是可控的,不可控就不管,可控異常進(jìn)行處理,不管是不是可控的,都先記錄一下
try:
pass
except Exception:
先記錄異常
能處理就處理
不能處理:raise
5.字符問題
- 如何表示字符: map 65 -> a 66 -> b :ASCII 一個字符占:8 bit: 2^8 -> 256 => 127
- GB2312 # GBK (等長編碼)
- Unicode 編碼 16 2^6 (等長編碼)
- UTF-8(不等長\變長編碼)
bytes = '張三'.encode("GBK")
print(bytes)
print(type(bytes))
byte_utf8 = '張三'.encode("utf-8")
print(byte_utf8)
str = bytes.decode("GBK")
print(str)
# 亂碼
str = byte_utf8.decode("GBK")
print(str)
b'\xd5\xc5\xc8\xfd'
<class 'bytes'>
b'\xe5\xbc\xa0\xe4\xb8\x89'
張三
# 亂碼
寮犱笁
6.文件操作
文本文件:
文本文件本質(zhì)上存儲時,也是二進(jìn)制,但可以用文本編輯器查看二進(jìn)制文件
二進(jìn)制文件無法通過文本編輯器查看
- 以'utf=8'的編碼、追加('a')方式“demo.txt”文件,并使用 .write(str)函數(shù)寫入,最后用 .close()函數(shù)關(guān)閉文件
try:
f = open("D://demo.txt", 'a', encoding='utf-8')
f.write("neuedu\n")
f.write("NEUQ\n")
finally:
f.close()
- 用with就不需要.close()方法關(guān)閉文件:
with open("D://demo.txt", 'a', encoding='utf-8') as f:
f.write("neuedu\n")
f.write("NEUQ\n")
-
readline()和readlines():
with open("D://demo.txt", encoding='utf-8') as f:
# 全部讀入
content = f.read()
print(content)
# 讀入一行
line = f.readline()
print(line)
# 每行都讀入,返回一個列表
for line in f.readlines():
print(line)
-
文件的打開模式
- r:以只讀方式打開文件,文件的指針會放在文件的開頭,這是默認(rèn)模式,如果文件不存在,拋出異常
- w:以只寫方式打開文件,如果文件存在會被覆蓋,如果文件不存在,則創(chuàng)建新文件
- a:以追加方式打開文件,如果文件已存在,則指針會放在文件的結(jié)尾,如果文件不存在,則創(chuàng)建文件
- r+:以讀寫方式打開文件,文件的指針放在文件的開頭,如果文件不存在,則拋出異常
- w+:以讀寫方式打開文件,如果文件存在,會被覆蓋,如果不存在,則創(chuàng)建文件
- a+:以讀寫方式打開文件,如果文件存在,則指針在文件的末尾,如果不存在,則創(chuàng)建文件