Python(3)—— 列表推導(dǎo)式,文件操作谤祖,類和對(duì)象

一婿滓、列表推導(dǎo)式:用來創(chuàng)建列表

> 所謂的列表推導(dǎo)式,就是指的輕量級(jí)循環(huán)創(chuàng)建列表

格式:
列表推導(dǎo)式的常見形式: my_list = [ item? ? for item in iterable]
my_list: 列表名 (變量名,? 屬于標(biāo)識(shí)符)
item: 將要存放到列表中的內(nèi)容
for item in iterable:? 非常標(biāo)準(zhǔn)的for循環(huán)表達(dá)式

[expr for iter in iterable if cond_expr]
expr: 將要存放到列表中的內(nèi)容
iter: 遍歷的每一項(xiàng)內(nèi)容
????iterable: 遍歷的對(duì)象
????if cond_expr: 條件表達(dá)式, 只有滿足當(dāng)前條件的,才能存放到列表中.

例如:
my_list = [x*x for x in range(10)]
print(my_list)
my_list1 = [x**2 for x in range(6)]
print(my_list1)

結(jié)果:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 4, 9, 16, 25]

使用if的情況:

例如:
list = [x for x in range(3, 10) if x % 2 == 0]
print(list)
結(jié)果: [4, 6, 8]

例如:
list = [11, 10, 9, 8, 7, 6]
[x for x in list if x % 2]
結(jié)果:[11, 9, 7]

例如:
llist = [x for x in 'hello python' if x != ' ' and x != 'l']
print(llist)
結(jié)果: ['h', 'e', 'o', 'p', 'y', 't', 'h', 'o', 'n']

例如:
llist = ['哈哈' for x in range(3)]
print(llist)
結(jié)果: ['哈哈','哈哈' ,'哈哈']

例如:
llist = ['%d' % (i+1) for i in range(3)] #等同于llist = [str(i+1) for i in range(3)]
print(llist)
結(jié)果: ['1',?'2' ,?'3'?]?

二粥喜、文件操作

> 什么是文件?? ? ? 能夠保存數(shù)據(jù)的集合. JPEG的壓縮性能太強(qiáng)凸主,壓縮后,展開额湘,壓縮卿吐,展開...10次打開就很模糊,壓縮時(shí)很多像素點(diǎn)剔除了锋华,效果不好嗡官。所以網(wǎng)絡(luò)傳輸中,傳jpeg的話毯焕,壓縮后展開還原不到原來的程度衍腥。所以我們常用png用于傳輸,它的壓縮性能不好纳猫。

1. 文件操作介紹

在操作文件的整體過程
> 1. 打開文件婆咸,或者新建立一個(gè)文件
> 2. 讀/寫數(shù)據(jù)
> 3. 關(guān)閉文件

2.? 文件的打開與關(guān)閉

1)? 打開文件

在python,使用open函數(shù)芜辕,可以打開一個(gè)已經(jīng)存在的文件擅耽,或者創(chuàng)建一個(gè)新文件.

說明:
* 使用open的時(shí)候,如果文件已經(jīng)存在,則直接打開.
* 如果不存在,就創(chuàng)建一個(gè)新文件.

打開的方式: open(文件名,訪問模式)

例如: f = open('test.txt', 'w') #如果是r的權(quán)限可以省略不寫

| 訪問模式: |? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
| r? ? ? ? | 以只讀方式打開文件物遇。文件的指針將會(huì)放在文件的開頭乖仇。這是默認(rèn)模式。如果文件不存在會(huì)報(bào)錯(cuò) |
| w? ? ? ? | 打開一個(gè)文件只用于寫入询兴。如果該文件已存在則將其覆蓋乃沙。如果該文件不存在,創(chuàng)建新文件诗舰。 |

| a? ? ? ? | 打開一個(gè)文件用于追加警儒。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾眶根。也就是說蜀铲,新的內(nèi)容將會(huì)被寫入到已有內(nèi)容之后。如果該文件不存在属百,創(chuàng)建新文件進(jìn)行寫入记劝。 |
| rb? ? ? ? | 以二進(jìn)制格式打開一個(gè)文件用于只讀。文件指針將會(huì)放在文件的開頭族扰。這是默認(rèn)模式厌丑。 |
| wb? ? ? ? | 以二進(jìn)制格式打開一個(gè)文件只用于寫入定欧。如果該文件已存在則將其覆蓋。如果該文件不存在怒竿,創(chuàng)建新文件砍鸠。 |
| ab? ? ? ? | 以二進(jìn)制格式打開一個(gè)文件用于追加。如果該文件已存在耕驰,文件指針將會(huì)放在文件的結(jié)尾爷辱。也就是說,新的內(nèi)容將會(huì)被寫入到已有內(nèi)容之后朦肘。如果該文件不存在托嚣,創(chuàng)建新文件進(jìn)行寫入。 |
| r+? ? ? ? | 打開一個(gè)文件用于讀寫厚骗。文件指針將會(huì)放在文件的開頭。? ? ? ? ? |
| w+? ? ? ? | 打開一個(gè)文件用于讀寫兢哭。如果該文件已存在則將其覆蓋领舰。如果該文件不存在,創(chuàng)建新文件迟螺。 |
| a+? ? ? ? | 打開一個(gè)文件用于讀寫冲秽。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾矩父。文件打開時(shí)會(huì)是追加模式锉桑。如果該文件不存在,創(chuàng)建新文件用于讀寫窍株。 |
| rb+? ? ? | 以二進(jìn)制格式打開一個(gè)文件用于讀寫民轴。文件指針將會(huì)放在文件的開頭。 |
| wb+? ? ? | 以二進(jìn)制格式打開一個(gè)文件用于讀寫球订。如果該文件已存在則將其覆蓋后裸。如果該文件不存在,創(chuàng)建新文件冒滩。 |
| ab+? ? ? | 以二進(jìn)制格式打開一個(gè)文件用于追加微驶。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾开睡。如果該文件不存在因苹,創(chuàng)建新文件用于讀寫推姻。 |

2)? 關(guān)閉文件

關(guān)閉格式:close()

例如:
# 新建一個(gè)文件驱闷,文件名為:test.txt
f = open('test.txt', 'w')
# 關(guān)閉這個(gè)文件
f.close()

3. 文件的讀寫

1) 寫數(shù)據(jù)? ? ------>? write

> 使用write()可以完成向文件寫入數(shù)據(jù)

例如:
f = open('test.txt', 'w', encoding='utf-8')
#寫入有中文時(shí),要加入這個(gè)編碼方式瓦糕,防止亂碼胁艰,內(nèi)存編碼方式bgk蘸秘,文件讀取到內(nèi)存就會(huì)# 變成gbk官卡,寫入到文件中時(shí)又會(huì)從bgk變成utf-8
str = '''既然你誠心誠意的問了,'''
f.write(str)
f.close()

我們會(huì)發(fā)現(xiàn), 不但創(chuàng)建了一個(gè)新的文件,而且文件中還添加上了上面的語句.

**注意**:

- 如果文件不存在那么創(chuàng)建醋虏,如果存在那么就先清空寻咒,然后寫入數(shù)據(jù)

2) 讀數(shù)據(jù)? ---->? read

> 使用read(num)可以從文件中讀取數(shù)據(jù),num表示要從文件中讀取的數(shù)據(jù)的長(zhǎng)度(單位是字節(jié))

> 如果沒有傳入num颈嚼,那么就表示讀取文件中所有的數(shù)據(jù)

例如:
f = open('test.txt', 'r', encoding='utf-8')
content = f.read(5)? # 最多讀取5個(gè)數(shù)據(jù)毛秘,換行符也占1個(gè)位
print(content)
print("-"*30)? # 分割線,用來測(cè)試
content = f.read()? # 從上次讀取的位置繼續(xù)讀取剩下的所有的數(shù)據(jù)
print(content)
f.close()? # 關(guān)閉文件阻课,這個(gè)可以是個(gè)好習(xí)慣哦

結(jié)果:
竟然你誠心
------------------------------
誠意的發(fā)問了叫挟,

注意:

- 如果用open打開文件時(shí),如果使用的"r"限煞,那么可以省略抹恳,即只寫 `open('test.txt')`

3) 讀數(shù)據(jù) ------>? readlines,讀取多行

> 就像read沒有參數(shù)時(shí)一樣,? readlines可以按照行的方式把整個(gè)文件中的內(nèi)容進(jìn)行一次性讀取署驻,并且返回的是一個(gè)列表奋献,其中每一行的數(shù)據(jù)為一個(gè)元素

例如:
f = open('test.txt', 'r', encodint='utf-8')
content = f.readlines()
print(type(content))
i=1
for temp in content:
????print("%d:%s" % (i, temp))
????i += 1
f.close()

結(jié)果:
<class 'list'>
1:竟然你誠心誠意的發(fā)問了,
2:納我就大發(fā)慈悲的告訴你旺上,

4)? 讀數(shù)據(jù) -----> readline瓶蚂,讀取單行

f = open('test.txt', 'r', encoding='utf-8')
content = f.readline()
print("1:%s" % content)
content = f.readline()
print("2:%s" % content)
f.close()

結(jié)果:
1:竟然你誠心誠意的發(fā)問了,
2:納我就大發(fā)慈悲的告訴你宣吱,

4. 應(yīng)用: 制作文件的備份

給文件做備份的步驟:
1. 打開文件
2. 讀取文件數(shù)據(jù)
3. 創(chuàng)建一個(gè)復(fù)制文件
4. 把讀取的數(shù)據(jù)寫入復(fù)制文件中
5. 關(guān)閉文件

代碼:
# # 創(chuàng)建一個(gè)原文件
# # 打開文件
old_f = open("hm.txt", "w")
# # 寫入數(shù)據(jù)
old_f.write("helloworld")
# # 關(guān)閉文件
old_f.close()

# 做備份文件 -> 偽代碼
# 01 打開hm.txt文件
# 02 讀取hm.txt文件的數(shù)據(jù)
# 03 創(chuàng)建一個(gè)hm[復(fù)件].txt文件
# 04 把從hm.txt讀取的數(shù)據(jù)寫入到hm[復(fù)件].txt文件中
# 05關(guān)閉文件

# 01 打開hm.txt文件
old_f = open("hm.txt", "r")
# 02 讀取hm.txt文件的數(shù)據(jù)
result = old_f.read()
# 03 創(chuàng)建一個(gè)hm[復(fù)件].txt文件
new_f = open("hm[復(fù)件].txt", "w")
# 04 把從hm.txt讀取的數(shù)據(jù)寫入到hm[復(fù)件].txt文件中
new_f.write(result)
# 05關(guān)閉文件
old_f.close()
new_f.close()

5. 文件? 文件夾的相關(guān)操作

>? 有些時(shí)候窃这,需要對(duì)文件進(jìn)行重命名、刪除等一些操作征候,python的os模塊中都有這么功能

1) 文件重命名

> os模塊中的rename()可以完成對(duì)文件的重命名操作

格式:
import os
os.rename(需要修改的文件名, 新的文件名)

例如:
import os
os.rename("畢業(yè)論文.txt", "畢業(yè)論文-最終版.txt")

2) 刪除文件

> os模塊中的remove()可以完成對(duì)文件的刪除操作

格式:
import os
os.remove(待刪除的文件名)

例如:
import os
os.remove("畢業(yè)論文.txt")

3) 創(chuàng)建文件夾

> os模塊中的mkdir()可以完成創(chuàng)建文件夾
import os
os.mkdir(文件夾名)

例如:
import os
os.mkdir("張三")

4) 獲取當(dāng)前目錄

> 獲取文件所在的目錄地址

# 獲取的是絕對(duì)路徑(可以看到盤符)?
import os
path = os.getcwd()
print(path)

5)? 改變默認(rèn)目錄

>? 改變當(dāng)前文件的默認(rèn)路徑

# ../ 上一級(jí)目錄 ./ 或者../ 都是相對(duì)路徑
# ./ 當(dāng)前目錄
# ../../上一級(jí)的上一級(jí)目錄

import os
os.chdir("../")

6)? 獲取目錄列表

# .idea python項(xiàng)目中個(gè)一個(gè)隱藏文件
# 文件名以.開頭的就是一個(gè)隱藏文件
import os
os.listdir("./")

7)? 刪除文件夾

import os
os.rmdir(文件夾名)

6. 應(yīng)用: 批量修改文件名

import os
# 準(zhǔn)備工作
# 01 當(dāng)前目錄下創(chuàng)建一個(gè)文件夾
os.mkdir("黑馬文件夾")

# 02 指定默認(rèn)目錄
os.chdir("黑馬文件夾")
print(os.getcwd())

# 03 在黑馬文件夾下面創(chuàng)建10個(gè)文件
for i in range(1, 11):
????# 打開文件
????f =open("hm%d.txt" % i, "w")
????# 關(guān)閉文件
????f.close()

# 實(shí)際工作
hmx.txt -> hmx[中國].txt
# 01 指定默認(rèn)目錄
os.chdir("黑馬文件夾")
# 02 獲取當(dāng)前目錄下的目錄列表
my_list = os.listdir()
# 03 遍歷my_list
for file_name in my_list:
????# 得的新的文件名
????new_file_name = file_name.replace(".txt", "[中國].txt")
????# 對(duì)文件重命名
????os.rename(file_name, new_file_name)

六.面向?qū)ο蠡A(chǔ)杭攻,面向?qū)ο蟮恼Z言特征:封裝,繼承疤坝,多態(tài)

1. 面向?qū)ο缶幊探榻B

**請(qǐng)用程序描述如下事情:**
- A同學(xué)報(bào)道登記信息
- B同學(xué)報(bào)道登記信息
- C同學(xué)報(bào)道登記信息
- A同學(xué)做自我介紹
- B同學(xué)做自我介紹
- C同學(xué)做自我介紹

# 面向過程編程
stu_a = {
????"name":"A",
????"age":21,
????"gender":1,
????"hometown":"河北"}

stu_b = {
????"name":"B",
????"age":22,
????"gender":0,
????"hometown":"山東"}

stu_c = {
????"name":"C",
????"age":20,
????"gender":1,
????"hometown":"安徽"}

def stu_intro(stu):
????"""自我介紹"""
????for key, value in stu.items():
????print("key=%s, value=%d"%(key,value))

stu_intro(stu_a)
stu_intro(stu_b)
stu_intro(stu_c)

考慮現(xiàn)實(shí)生活中朴上,我們的思維方式是放在學(xué)生這個(gè)個(gè)人上,是學(xué)生做了自我介紹卒煞。而不是像我們剛剛寫出的代碼痪宰,先有了介紹的行為,再去看介紹了誰畔裕。

用我們的現(xiàn)實(shí)思維方式該怎么用程序表達(dá)呢衣撬?

# 面向?qū)ο蟮木幊痰脑挘覀儠?huì)創(chuàng)建一個(gè)Student的類扮饶,這個(gè)類會(huì)接收一些個(gè)人信息的參數(shù)
stu_a = Student(個(gè)人信息)
stu_b = Student(個(gè)人信息)
stu_c = Student(個(gè)人信息)

stu_a.intro()
stu_b.intro()
stu_c.intro()

- 面向過程:根據(jù)業(yè)務(wù)邏輯從上到下寫代碼

- 面向?qū)ο螅簩?shù)據(jù)與函數(shù)綁定到一起具练,進(jìn)行封裝,這樣能夠更快速的開發(fā)程序甜无,減少了重復(fù)代碼的重寫過程

面向過程編程最易被初學(xué)者接受扛点,其往往用一長(zhǎng)段代碼來實(shí)現(xiàn)指定功能哥遮,開發(fā)過程的思路是將數(shù)據(jù)與函數(shù)按照?qǐng)?zhí)行的邏輯順序組織在一起,數(shù)據(jù)與函數(shù)分開考慮陵究。

今天我們來學(xué)習(xí)一種新的編程方式:面向?qū)ο缶幊蹋∣bject Oriented Programming眠饮,OOP,面向?qū)ο蟪绦蛟O(shè)計(jì))

1)解決菜鳥買電腦的故事

第一種方式:

> 1)在網(wǎng)上查找資料

> 2)根據(jù)自己預(yù)算和需求定電腦的型號(hào) MacBook 15 頂配 1W8

> 3)去市場(chǎng)找到蘋果店各種店無法甄別真假 隨便找了一家

> 4)找到業(yè)務(wù)員,業(yè)務(wù)員推薦了另外一款 配置更高價(jià)格便宜,也是蘋果系統(tǒng)的 1W

> 5)砍價(jià)30分鐘 付款9999

> 6)成交

> 回去之后發(fā)現(xiàn)各種問題

第二種方式 :

> 1)找一個(gè)靠譜的電腦高手

> 2)給錢交易

需要了解的定義性文字:

面向?qū)ο?object-oriented ;簡(jiǎn)稱: OO) 至今還沒有統(tǒng)一的概念 我這里把它定義為: 按人們 認(rèn)識(shí)客觀世界的系統(tǒng)思維方式,采用基于對(duì)象(實(shí)體) 的概念建立模型,模擬客觀世界分析铜邮、設(shè) 計(jì)仪召、實(shí)現(xiàn)軟件的辦法。

面向?qū)ο缶幊?Object Oriented Programming-OOP) 是一種解決軟件復(fù)用的設(shè)計(jì)和編程方法松蒜。 這種方法把軟件系統(tǒng)中相近相似的操作邏輯和操作 應(yīng)用數(shù)據(jù)扔茅、狀態(tài),以類的型式描述出來,以對(duì)象實(shí)例的形式在軟件系統(tǒng)中復(fù)用,以達(dá)到提高軟件開發(fā)效率的作用。

2. 類和對(duì)象

面向?qū)ο缶幊痰?個(gè)非常重要的概念:類和對(duì)象

對(duì)象是面向?qū)ο缶幊痰暮诵慕彰纾谑褂脤?duì)象的過程中召娜,為了將具有共同特征和行為的一組對(duì)象抽象定義,提出了另外一個(gè)新的概念——類

類就相當(dāng)于制造飛機(jī)時(shí)的圖紙惊楼,用它來進(jìn)行創(chuàng)建的飛機(jī)就相當(dāng)于對(duì)象

1)? 類

人以類聚 物以群分玖瘸。

具有相似內(nèi)部狀態(tài)和運(yùn)動(dòng)規(guī)律的實(shí)體的集合(或統(tǒng)稱為抽象)。

具有相同屬性和行為事物的統(tǒng)稱

類是抽象的,在使用的時(shí)候通常會(huì)找到這個(gè)類的一個(gè)具體的存在,使用這個(gè)具體的存在胁后。一個(gè)類可以找到多個(gè)對(duì)象

2)? 對(duì)象

某一個(gè)具體事物的存在 ,在現(xiàn)實(shí)世界中可以是看得見摸得著的。

可以是直接使用的

3)? 類和對(duì)象之間的關(guān)系

小總結(jié):類就是創(chuàng)建對(duì)象的模板

4) 類的構(gòu)成

類(Class) 由3個(gè)部分構(gòu)成
- 類的名稱:類名
- 類的屬性:一組數(shù)據(jù)
- 類的方法:允許對(duì)進(jìn)行操作的方法 (行為)

5)? 類的抽象

擁有相同(或者類似)屬性和行為的對(duì)象都可以抽像出一個(gè)類

3* 定義類

定義一個(gè)類嗦枢,格式如下:
class 類名:
????方法列表 —— 方法就是函數(shù)

定義一個(gè)Hero類
# 經(jīng)典類(舊式類)定義形式:
# class Hero:
# class Hero():

# 新式類定義形式
class Hero(object): ——這里的object是所有類的父類
? ? # 這是一個(gè)實(shí)例方法攀芯,或者稱為對(duì)象方法
????def info(self):
????????print("英雄各有見,何必問出處文虏。")

說明:

- 定義類時(shí)有2種形式:新式類和經(jīng)典類侣诺,上面代碼中的Hero為新式類,前兩行注釋部分則為經(jīng)典類氧秘;
- object 是Python 里所有類的最頂級(jí)父類年鸳;
- 類名 的命名規(guī)則按照"大駝峰命名法";
- info 是一個(gè)實(shí)例方法丸相,第一個(gè)參數(shù)一般是self搔确,表示實(shí)例對(duì)象本身,當(dāng)然了可以將self換為其它的名字灭忠,其作用是一個(gè)變量 這個(gè)變量指向了實(shí)例對(duì)象

4*? 創(chuàng)建對(duì)象

python中膳算,可以根據(jù)已經(jīng)定義的類去創(chuàng)建出一個(gè)或多個(gè)對(duì)象。

創(chuàng)建對(duì)象的格式為:
對(duì)象名1 = 類名()
對(duì)象名2 = 類名()
對(duì)象名3 = 類名()

class Hero(object):? # 新式類定義形式
????"""info 是一個(gè)實(shí)例方法弛作,類對(duì)象可以調(diào)用實(shí)例方法涕蜂,實(shí)例方法的第一個(gè)參數(shù)一定是self"""
????def info(self):
????????"""當(dāng)對(duì)象調(diào)用實(shí)例方法時(shí),Python會(huì)自動(dòng)將對(duì)象本身的引用做為參數(shù)映琳,
????????????傳遞到實(shí)例方法的第一個(gè)參數(shù)self里"""
????????print(self)
????????print("self各不同机隙,對(duì)象是出處蜘拉。")

# Hero這個(gè)類 實(shí)例化了一個(gè)對(duì)象? taidamier(泰達(dá)米爾)
taidamier = Hero()

# 對(duì)象調(diào)用實(shí)例方法info(),執(zhí)行info()里的代碼
# . 表示選擇屬性或者方法
taidamier.info()

print(taidamier)? # 打印對(duì)象有鹿,則默認(rèn)打印對(duì)象所在類的內(nèi)存的地址旭旭,16進(jìn)制的地址,以ox或oX開頭的一長(zhǎng)串印颤,結(jié)果等同于info里的print(self)
print(id(taidamier))? # id(taidamier) 則是內(nèi)存地址的十進(jìn)制形式表示

說明:

* 用類創(chuàng)建一個(gè)對(duì)象時(shí)您机,類似于用一個(gè)模子,來制造實(shí)物

> 對(duì)象既然有實(shí)例方法年局,也可以有自己的屬性

5*? 添加和獲取對(duì)象的屬性

類創(chuàng)建出來的對(duì)象,可以添加屬性

例如:

class Hero(object):
????"""定義了一個(gè)英雄類际看,可以移動(dòng)和攻擊"""
????def move(self):
????????"""實(shí)例方法"""
????????print("正在前往事發(fā)地點(diǎn)...")

? ? def attack(self):
????????"""實(shí)例方法"""
????????print("發(fā)出了一招強(qiáng)力的普通攻擊...")

# 實(shí)例化了一個(gè)英雄對(duì)象 泰達(dá)米爾
taidamier = Hero()

# 給對(duì)象添加屬性,以及對(duì)應(yīng)的屬性值
taidamier.name = "泰達(dá)米爾"? # 姓名
taidamier.hp = 2600? # 生命值
taidamier.atk = 450? # 攻擊力
taidamier.armor = 200? # 護(hù)甲值

# 通對(duì).成員選擇運(yùn)算符矢否,獲取對(duì)象的屬性值
print("英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp))
print("英雄 %s 的攻擊力 :%d" % (taidamier.name, taidamier.atk))
print("英雄 %s 的護(hù)甲值 :%d" % (taidamier.name, taidamier.armor))

# 通過.成員選擇運(yùn)算符仲闽,獲取對(duì)象的實(shí)例方法
taidamier.move()
taidamier.attack()

> 對(duì)象創(chuàng)建并添加屬性后,可以在類的實(shí)例方法里獲取這些屬性

6*? 在方法內(nèi)通過self獲取對(duì)象屬性

class Hero(object):
????"""定義了一個(gè)英雄類僵朗,可以移動(dòng)和攻擊"""
? ? def move(self):
# self是個(gè)形參赖欣,誰(taidamier?)調(diào)用了move這個(gè)方法,誰就會(huì)傳到self里去
????????"""實(shí)例方法"""
????????print("正在前往事發(fā)地點(diǎn)...")
????def attack(self):
????????"""實(shí)例方法"""
????????print("發(fā)出了一招強(qiáng)力的普通攻擊...")
????def info(self):
????????"""在類的實(shí)例方法中验庙,通過self獲取該對(duì)象的屬性"""
????????print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
????????print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
????????print("英雄 %s 的護(hù)甲值 :%d" % (self.name, self.armor))

# 實(shí)例化了一個(gè)英雄對(duì)象 泰達(dá)米爾
taidamier = Hero()

# 給對(duì)象添加屬性顶吮,以及對(duì)應(yīng)的屬性值
taidamier.name = "泰達(dá)米爾"? # 姓名
taidamier.hp = 2600? # 生命值
taidamier.atk = 450? # 攻擊力
taidamier.armor = 200? # 護(hù)甲值

# 通過.成員選擇運(yùn)算符,獲取對(duì)象的實(shí)例方法
taidamier.info()? # 只需要調(diào)用實(shí)例方法info()粪薛,即可獲取英雄的屬性
taidamier.move()
taidamier.attack()

> 創(chuàng)建對(duì)象后再去添加屬性有點(diǎn)不合適悴了,更簡(jiǎn)單的,可以在創(chuàng)建對(duì)象的時(shí)候违寿,就已經(jīng)擁有這些屬性

7*? 魔法方法 `__init__()`

class Hero(object):
????"""定義了一個(gè)英雄類湃交,可以移動(dòng)和攻擊"""
????# Python 的類里提供的,兩個(gè)下劃線開始藤巢,兩個(gè)下劃線結(jié)束的方法搞莺,就是魔法方法,__init__()就是一個(gè)魔法方法掂咒,通常用來做屬性初始化 或 賦值 操作才沧。
????# 如果類里面沒有寫__init__方法,Python會(huì)自動(dòng)創(chuàng)建绍刮,但是不執(zhí)行任何操作糜工,
????# 如果為了能夠在完成自己想要的功能,可以自己定義__init__方法录淡,
????# 所以一個(gè)類里無論自己是否編寫__init__方法 一定有__init__方法捌木。
? ? # 魔法方法,又叫構(gòu)造方法
? ? # 類在創(chuàng)建對(duì)象的時(shí)候嫉戚,它內(nèi)部會(huì)執(zhí)行的一些方法刨裆,就是魔法方法澈圈,它會(huì)把內(nèi)部的魔法方法走完,才會(huì)把這個(gè)對(duì)象創(chuàng)建出來

? ? # init的self不是對(duì)象
????def __init__(self):
????????""" 方法帆啃,用來做變量初始化 或 賦值 操作瞬女,在類實(shí)例化對(duì)象的時(shí)候,會(huì)被自動(dòng)調(diào)用"""
????????self.name = "泰達(dá)米爾" # 姓名
????????self.hp = 2600 # 生命值
????????self.atk = 450? # 攻擊力
????????self.armor = 200? # 護(hù)甲值

? ? def move(self):
????????"""實(shí)例方法"""
????????print("正在前往事發(fā)地點(diǎn)...")
????def attack(self):
????????"""實(shí)例方法"""
????????print("發(fā)出了一招強(qiáng)力的普通攻擊...")

# 實(shí)例化了一個(gè)英雄對(duì)象努潘,并自動(dòng)調(diào)用__init__()方法
taidamier = Hero()

# 通過.成員選擇運(yùn)算符诽偷,獲取對(duì)象的實(shí)例方法
taidamier.info() # 只需要調(diào)用實(shí)例方法info(),即可獲取英雄的屬性
taidamier.move()
taidamier.attack()

說明:

- `__init__()`方法疯坤,在創(chuàng)建一個(gè)對(duì)象時(shí)默認(rèn)被調(diào)用报慕,不需要手動(dòng)調(diào)用

- `__init__(self)`中的self參數(shù),不需要開發(fā)者傳遞压怠,python解釋器會(huì)自動(dòng)把當(dāng)前的對(duì)象引用傳遞過去眠冈。

總結(jié):

* `__init__`方法也被成為構(gòu)造方法

* 在python中,以`__`開頭,以`__`結(jié)尾的方法,我們成為魔法方法

* 這個(gè)方法是由python提供給我們的,也可以理解為是由python中的object類,提供給我的.

* python可以通過這些魔法方法監(jiān)聽我們創(chuàng)建對(duì)象的進(jìn)度

* 程序員也可以在自定義的類中,? 重寫該魔法方法,? 在方法中做自己的事情.

* 注意. 當(dāng)進(jìn)入`__init__`這個(gè)魔法方法的時(shí)候, 對(duì)象已經(jīng)創(chuàng)建成功了.

> 在類的方法里定義屬性的固定值,則每個(gè)對(duì)象實(shí)例變量的屬性值都是相同的菌瘫。

> 一個(gè)游戲里往往有很多不同的英雄蜗顽,也可以讓實(shí)例化的每個(gè)對(duì)象,都有不同的屬性值

8*? 有參數(shù)的`__init__()`方法

class Hero(object):
????"""定義了一個(gè)英雄類雨让,可以移動(dòng)和攻擊"""
????def __init__(self, name, skill, hp, atk, armor):
? ? """ __init__() 方法雇盖,用來做變量初始化 或 賦值 操作"""
????????# 英雄名
????????self.name = name
?????????# 技能
????????self.skill = skill
????????# 生命值:
????????self.hp = hp
????????# 攻擊力
????????self.atk = atk
????????# 護(hù)甲值
????????self.armor = armor
? ? ? ? # 在類里面調(diào)用實(shí)例方法,用self
? ? ? ? self.move()

????def move(self):
????????"""實(shí)例方法"""
????????print("%s 正在前往事發(fā)地點(diǎn)..." % self.name)

? ? def attack(self):
????????"""實(shí)例方法"""
????????print("發(fā)出了一招強(qiáng)力的%s..." % self.skill)

? ? def info(self):
????????print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
????????print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
????????print("英雄 %s 的護(hù)甲值 :%d" % (self.name, self.armor))

# 實(shí)例化英雄對(duì)象時(shí)栖忠,參數(shù)會(huì)傳遞到對(duì)象的__init__()方法里
taidamier = Hero("泰達(dá)米爾", "旋風(fēng)斬", 2600, 450, 200)
gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400)
# print(gailun)
# print(taidamier)

# 不同對(duì)象的屬性值的單獨(dú)保存
print(id(taidamier.name))
print(id(gailun.name))

# 同一個(gè)類的不同對(duì)象崔挖,實(shí)例方法共享
print(id(taidamier.move()))
print(id(gailun.move()))

說明:

- 通過一個(gè)類,可以創(chuàng)建多個(gè)對(duì)象娃闲,就好比 通過一個(gè)模具創(chuàng)建多個(gè)實(shí)體一樣

- `__init__(self)`中虚汛,默認(rèn)有1個(gè)參數(shù)名字為self匾浪,如果在創(chuàng)建對(duì)象時(shí)傳遞了2個(gè)實(shí)參皇帮,那么`__init__(self)`中出了self作為第一個(gè)形參外還需要2個(gè)形參,例如`__init__(self,x,y)`

注意:

1. 在類內(nèi)部獲取 屬性 和 實(shí)例方法蛋辈,通過self獲仁羰啊;

2. 在類外部獲取 屬性 和 實(shí)例方法冷溶,通過對(duì)象名獲取渐白。

3. 如果一個(gè)類有多個(gè)對(duì)象,每個(gè)對(duì)象的屬性是各自保存的逞频,都有各自獨(dú)立的地址纯衍;

4. 但是實(shí)例方法是所有對(duì)象共享的,只占用一份內(nèi)存空間苗胀。類會(huì)通過self來判斷是哪個(gè)對(duì)象調(diào)用了實(shí)例方法襟诸。

9*? 魔法方法: `__str__()`方法

class Hero(object):
????"""定義了一個(gè)英雄類瓦堵,可以移動(dòng)和攻擊"""
????def __init__(self, name, skill, hp, atk, armor):
????????""" __init__() 方法,用來做變量初始化 或 賦值 操作"""
????????# 英雄名
????????self.name = name? # 實(shí)例變量
????????# 技能
????????self.skill = skill
????????# 生命值:
????????self.hp = hp? # 實(shí)例變量
????????# 攻擊力
????????self.atk = atk
????????# 護(hù)甲值
????????self.armor = armor

? ? def move(self):
????????"""實(shí)例方法"""
????????print("%s 正在前往事發(fā)地點(diǎn)..." % self.name)

? ? def attack(self):
????????"""實(shí)例方法"""
????????print("發(fā)出了一招強(qiáng)力的%s..." % self.skill)

? ? # def info(self):
????#? ? print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
????#? ? print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
????#? ? print("英雄 %s 的護(hù)甲值 :%d" % (self.name, self.armor))

? ? def __str__(self):
????????"""
????????????這個(gè)方法是一個(gè)魔法方法 (Magic Method) 歌亲,用來顯示信息
? ? ? ? ? ? 沒有參數(shù)菇用,只有一個(gè)返回值,而且返回值必須是一個(gè)字符串
????????????該方法需要 return 一個(gè)數(shù)據(jù)陷揪,并且只有self一個(gè)參數(shù)惋鸥,當(dāng)在類的外部 print(對(duì)象) 則打印這個(gè)數(shù)據(jù)
????????"""
????????return "英雄 <%s> 數(shù)據(jù): 生命值 %d, 攻擊力 %d, 護(hù)甲值 %d" % (self.name, self.hp, self.atk, self.armor)

taidamier = Hero("泰達(dá)米爾", "旋風(fēng)斬", 2600, 450, 200)
gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400)

# 如果沒有__str__ 則默認(rèn)打印 對(duì)象在內(nèi)存的地址。
# 當(dāng)類的實(shí)例化對(duì)象 擁有 __str__ 方法后悍缠,那么打印對(duì)象則打印 __str__ 的返回值
print(taidamier)
print(gailun)

# 查看類的文檔說明卦绣,也就是類的注釋
print(Hero.__doc__)

說明:

- 在python中方法名如果是`__xxxx__()`的,那么就有特殊的功能扮休,因此叫做“魔法”方法

- 當(dāng)使用print輸出對(duì)象的時(shí)候迎卤,默認(rèn)打印對(duì)象的內(nèi)存地址。如果類定義了`__str__(self)`方法玷坠,那么就會(huì)打印從在這個(gè)方法中 `return` 的數(shù)據(jù)

- `__str__`方法通常返回一個(gè)字符串蜗搔,作為這個(gè)對(duì)象的描述信息

10* 魔法方法: `__del__()`方法(了解)

創(chuàng)建對(duì)象后,python解釋器默認(rèn)調(diào)用`__init__()`方法八堡;
當(dāng)刪除對(duì)象時(shí)樟凄,python解釋器也會(huì)默認(rèn)調(diào)用一個(gè)方法,這個(gè)方法為`__del__()`方法

class Hero(object):
????# 初始化方法
????# 創(chuàng)建完對(duì)象后會(huì)自動(dòng)被調(diào)用
????def __init__(self, name):
????????print('__init__方法被調(diào)用')
????????self.name = name

? ? # 當(dāng)對(duì)象被刪除時(shí)兄渺,會(huì)自動(dòng)被調(diào)用
????def __del__(self):
????????print("__del__方法被調(diào)用")
????????print("%s 被 GM 干掉了..." % self.name)

# 創(chuàng)建對(duì)象
taidamier = Hero("泰達(dá)米爾")

# 刪除對(duì)象
print("%d 被刪除1次" % id(taidamier))
del(taidamier) # 只有在del這個(gè)對(duì)象的時(shí)候缝龄,才會(huì)走_(dá)_del__

#引用計(jì)數(shù)
print("--" * 10)
gailun = Hero("蓋倫")
gailun1 = gailun
gailun2 = gailun
print("%d 被刪除1次" % id(gailun))
del(gailun)
print("%d 被刪除1次" % id(gailun1))
del(gailun1)
print("%d 被刪除1次" % id(gailun2))
del(gailun2) —— 引用計(jì)數(shù)為0時(shí),這個(gè)類才會(huì)被釋放挂谍, 走_(dá)_del__

總結(jié)

- 當(dāng)有變量保存了一個(gè)對(duì)象的引用時(shí)叔壤,此對(duì)象的引用計(jì)數(shù)就會(huì)加1;

- 當(dāng)使用del() 刪除變量指向的對(duì)象時(shí)口叙,則會(huì)減少對(duì)象的引用計(jì)數(shù)炼绘。如果對(duì)象的引用計(jì)數(shù)不為1,那么會(huì)讓這個(gè)對(duì)象的引用計(jì)數(shù)減1妄田,當(dāng)對(duì)象的引用計(jì)數(shù)為0的時(shí)候俺亮,則對(duì)象才會(huì)被真正刪除(內(nèi)存被回收)。

七疟呐、 繼承

1. 繼承的概念

- 在程序中脚曾,繼承描述的是多個(gè)類之間的所屬關(guān)系。

- 如果一個(gè)類A里面的屬性和方法可以復(fù)用启具,則可以通過繼承的方式本讥,傳遞到類B里。

- 那么類A就是基類,也叫做父類拷沸;類B就是派生類旨椒,也叫做子類。

# 父類
class A(object): —— object是所有類的父類
????def __init__(self):
????????self.num = 10
????def print_num(self):
????????print(self.num + 10)

# 子類
class B(A):
????pass

b = B()
print(b.num)
b.print_num()

計(jì)算結(jié)果:10堵漱,20

2*? 單繼承

> 單繼承:子類只繼承一個(gè)父類

# 定義一個(gè)Master類
class Master(object):
????def __init__(self):
????????# 屬性
????????self.kongfu = "古法煎餅果子配方"
? ? # 實(shí)例方法
????def make_cake(self):
????????print("按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

# 定義Prentice類综慎,繼承了 Master,則Prentice是子類勤庐,Master是父類示惊。
class Prentice(Master):
????#子類可以繼承父類所有的屬性和方法,哪怕子類沒有自己的屬性和方法愉镰,也可以使用父類的屬性和方法米罚。
????pass? ? ? ? ? ? ? ?

laoli = Master()
print(laoli.kongfu)
laoli.make_cake()
damao = Prentice()? # 創(chuàng)建子類實(shí)例對(duì)象
print(damao.kongfu) # 子類對(duì)象可以直接使用父類的屬性
damao.make_cake()? # 子類對(duì)象可以直接使用父類的方法

說明:

- 雖然子類沒有定義`__init__`方法初始化屬性,也沒有定義實(shí)例方法丈探,但是父類有录择。所以只要?jiǎng)?chuàng)建子類的對(duì)象,就默認(rèn)執(zhí)行了那個(gè)繼承過來的`__init__`方法

總結(jié):

- 子類在繼承的時(shí)候碗降,在定義類時(shí)隘竭,小括號(hào)()中為父類的名字

- 父類的屬性、方法讼渊,會(huì)被繼承給子類

3*? 多繼承

>? 多繼承:子類繼承多個(gè)父類

class Master(object):
????def __init__(self):
????# 實(shí)例變量动看,屬性
????????self.kongfu = "古法煎餅果子配方"
????# 實(shí)例方法,方法
????def make_cake(self):? ? ? ? ? ? ? ? ? ?
????????print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)
????def dayandai(self):
????????print("師傅的大煙袋..")

class School(object):
????def __init__(self):
????????self.kongfu = "現(xiàn)代煎餅果子配方"
????def make_cake(self):
????????print("[現(xiàn)代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)
????def xiaoyandai(self):
????????print("學(xué)校的小煙袋..")

# 多繼承爪幻,繼承了多個(gè)父類(School在前)
class Prentice(School, Master):
????pass

damao = Prentice()
print(damao.kongfu) ——執(zhí)行School的配方
damao.make_cake()
damao.dayandai()
damao.xiaoyandai()

class Prentice(Master, School):? # 多繼承菱皆,繼承了多個(gè)父類(Master在前)
????pass

damao = Prentice()
# 執(zhí)行Master的屬性
print(damao.kongfu)
# 執(zhí)行Master的實(shí)例方法
damao.make_cake()
# 子類的魔法屬性__mro__決定了屬性和方法的查找順序
print(Prentice.__mro__)

# 不重名不受影響
damao.dayandai()
damao.xiaoyandai()

說明:

- 多繼承可以繼承多個(gè)父類,也繼承了所有父類的屬性和方法

- 注意:如果多個(gè)父類中有同名的 屬性和方法挨稿,則默認(rèn)使用第一個(gè)父類的屬性和方法(根據(jù)類的魔法屬性**mro**的順序來查找)

- 多個(gè)父類中仇轻,不重名的屬性和方法,不會(huì)有任何影響奶甘。

4*? 子類重寫父類的同名屬性和方法

class Master(object):
????def __init__(self):
????????self.kongfu = "古法煎餅果子配方"

? ? def make_cake(self):
????????print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

class School(object):
????def __init__(self):
????????self.kongfu = "現(xiàn)代煎餅果子配方"

? ? def make_cake(self):
????????print("[現(xiàn)代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

class Prentice(School, Master):? # 多繼承篷店,繼承了多個(gè)父類
????def __init__(self):
????????self.kongfu = "貓氏煎餅果子配方"

? ? def make_cake(self):
????????print("[貓氏] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

# 如果子類和父類的方法名和屬性名相同,則默認(rèn)使用子類的
# 叫 子類重寫父類的同名方法和屬性
damao = Prentice()
print(damao.kongfu) # 子類和父類有同名屬性甩十,則默認(rèn)使用子類的
damao.make_cake() # 子類和父類有同名方法船庇,則默認(rèn)使用子類的
# 子類的魔法屬性__mro__決定了屬性和方法的查找順序
print(Prentice.__mro__)

5*? 子類調(diào)用父類同名屬性和方法

class Master(object):
????def make_cake(self):? ? ? ? ? ? ? ? ?
????????print("按照 [古法] 制作了一份煎餅果子...")

class School(object):
????def make_cake(self):
????????print(" 按照 [現(xiàn)代] 制作了一份煎餅果子...")

# 多繼承吭产,繼承了多個(gè)父類
class Prentice(School, Master):
????# 實(shí)例方法
????def make_cake(self):
????????print("按照 [貓氏] 制作了一份煎餅果子...")

? ? # 調(diào)用父類方法格式:父類類名.父類方法(self)
????def make_old_cake(self):
????????# 調(diào)用父類Master的實(shí)例方法
????????Master.make_cake(self)

? ? def make_new_cake(self):
????????# 調(diào)用父類School的實(shí)例方法
????????School.make_cake(self)

# 實(shí)例化對(duì)象侣监,自動(dòng)執(zhí)行子類的__init__方法
damao = Prentice()
damao.make_cake() # 調(diào)用子類的方法(默認(rèn)重寫了父類的同名方法)
print("--" * 10)
damao.make_old_cake() # 進(jìn)入實(shí)例方法去調(diào)用父類Master的方法
print("--" * 10)
damao.make_new_cake() # 進(jìn)入實(shí)例方法去調(diào)用父類School的方法
print("--" * 10)
damao.make_cake() # 調(diào)用本類的實(shí)例方法

執(zhí)行結(jié)果:
按照 [貓氏] 制作了一份煎餅果子...
--------------------
按照 [古法] 制作了一份煎餅果子...
--------------------
按照 [現(xiàn)代] 制作了一份煎餅果子...
--------------------
按照 [貓氏] 制作了一份煎餅果子...

6. super()的使用

class Master(object):
????# 實(shí)例方法,方法
????def make_cake(self):
????????print("按照 [古法] 制作了一份煎餅果子...")

# 父類是 Master類
class School(Master):
????# 實(shí)例方法臣淤,方法
????def make_cake(self):
????????print("按照 [現(xiàn)代] 制作了一份煎餅果子...")
????????# 執(zhí)行父類的實(shí)例方法
????????super().make_cake()

# 父類是 School 和 Master
# 多繼承橄霉,繼承了多個(gè)父類
class Prentice(School, Master):
????# 實(shí)例方法,方法
????def make_cake(self):
????????print("按照 [貓氏] 制作了一份煎餅果子...")

? ? def make_all_cake(self):
????????# 方式1. 指定執(zhí)行父類的方法(代碼臃腫)
????????# School.make_cake(self)
????????# Master.make_cake(self)

? ? ? ? # 方法2. super() 帶參數(shù)版本邑蒋,只支持新式類
????????# super(Prentice, self).make_cake()
????????# self.make_cake()

? ? ? ? # 方法3. super()的簡(jiǎn)化版姓蜂,只支持新式類
????????# 執(zhí)行父類的 實(shí)例方法
????????super().make_cake() —— super()一般指第一個(gè)父類

damao = Prentice()
damao.make_cake()
damao.make_all_cake()
# print(Prentice.__mro__)

知識(shí)點(diǎn):

> 子類繼承了多個(gè)父類按厘,如果父類類名修改了,那么子類也要涉及多次修改钱慢。而且需要重復(fù)寫多次調(diào)用逮京,顯得代碼臃腫。
> 使用super() 可以逐一調(diào)用所有的父類方法束莫,并且只執(zhí)行一次懒棉。調(diào)用順序遵循 **mro** 類屬性的順序。
> **注意:如果繼承了多個(gè)父類览绿,且父類都有同名方法策严,則默認(rèn)只執(zhí)行第一個(gè)父類的(同名方法只執(zhí)行一次,目前super()不支持執(zhí)行多個(gè)父類的同名方法)**
> super() 在Python2.3之后才有的機(jī)制饿敲,用于通常單繼承的多層繼承妻导。

八.? 面向?qū)ο?/h1>

>? 面向?qū)ο笕筇匦裕悍庋b、繼承怀各、多態(tài)

1. 私有權(quán)限? ---? 私有方法和私有屬性

封裝的意義:

1. 將屬性和方法放到一起做為一個(gè)整體倔韭,然后通過實(shí)例化對(duì)象來處理;

2. 隱藏內(nèi)部實(shí)現(xiàn)細(xì)節(jié)瓢对,只需要和對(duì)象及其屬性和方法交互就可以了狐肢;

3. 對(duì)類的屬性和方法增加 訪問權(quán)限控制。

私有權(quán)限:在屬性名和方法名 前面 加上兩個(gè)下劃線 __

> 1. 類的私有屬性 和 私有方法沥曹,都不能通過對(duì)象直接訪問份名,但是可以在本類內(nèi)部訪問;

> 2. 類的私有屬性 和 私有方法妓美,都不會(huì)被子類繼承僵腺,子類也無法訪問;

> 3. 私有屬性 和 私有方法 往往用來處理類的內(nèi)部事情壶栋,不通過對(duì)象處理辰如,起到安全作用。

class Master(object):
????def __init__(self):
????????self.kongfu = "古法煎餅果子配方"

? ? def make_cake(self):? ? ? ? ?
????????print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

class School(object):
????def __init__(self):
????????self.kongfu = "現(xiàn)代煎餅果子配方"

? ? def make_cake(self):
????????print("[現(xiàn)代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

class Prentice(School, Master):
????def __init__(self):
????????self.kongfu = "貓氏煎餅果子配方"
????????# 私有屬性贵试,可以在類內(nèi)部通過self調(diào)用琉兜,但不能通過對(duì)象訪問
????????self.__money = 10000?

? ? # 私有方法,可以在類內(nèi)部通過self調(diào)用毙玻,但不能通過對(duì)象訪問
????def __print_info(self):
????????print(self.kongfu)
????????print(self.__money)

? ? def make_cake(self):
????????self.__init__()
????????print("[貓氏] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

? ? def make_old_cake(self):
????????Master.__init__(self)
????????Master.make_cake(self)

? ? def make_new_cake(self):
????????School.__init__(self)
????????School.make_cake(self)

class PrenticePrentice(Prentice):
????pass

damao = Prentice()
# 對(duì)象不能訪問私有權(quán)限的屬性和方法
print(damao.__money)
damao.__print_info()
pp = PrenticePrentice()

# 子類不能繼承父類私有權(quán)限的屬性和方法
print(pp.__money)
pp.__print_info()

總結(jié)

- Python中沒有像C++中 public 和 private 這些關(guān)鍵字來區(qū)別公有屬性和私有屬性豌蟋。

- Python是以屬性命名方式來區(qū)分,如果在屬性和方法名前面加了2個(gè)下劃線'__'桑滩,則表明該屬性和方法是私有權(quán)限梧疲,否則為公有權(quán)限。

2.? 修改私有屬性的值

- 如果需要修改一個(gè)對(duì)象的屬性值,通常有2種方法

? > 1. 對(duì)象名.屬性名 = 數(shù)據(jù) ----> 直接修改

? > 2. 對(duì)象名.方法名() ----> 間接修改

- 私有屬性不能直接訪問幌氮,所以無法通過第一種方式修改缭受,一般的通過第二種方式修改私有屬性的值:定義一個(gè)可以調(diào)用的公有方法,在這個(gè)公有方法內(nèi)訪問修改该互。

class Master(object):
????def __init__(self):
????????self.kongfu = "古法煎餅果子配方"

? ? def make_cake(self):? ? ? ? ?
????????print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

class School(object):
????def __init__(self):
????????self.kongfu = "現(xiàn)代煎餅果子配方"

? ? def make_cake(self):
????????print("[現(xiàn)代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

class Prentice(School, Master):
????def __init__(self):
????????self.kongfu = "貓氏煎餅果子配方"
????????# 私有屬性米者,可以在類內(nèi)部通過self調(diào)用,但不能通過對(duì)象訪問
????????self.__money = 10000?

? ? # 現(xiàn)代軟件開發(fā)中宇智,通常會(huì)定義get_xxx()方法和set_xxx()方法來獲取和修改私有屬性值塘雳。
????# 返回私有屬性的值

????def get_money(self):
????????return self.__money

? ? # 接收參數(shù),修改私有屬性的值
? ? def set_money(self, num):
????????self.__money = num

? ? def make_cake(self):
????????self.__init__()
????????print("[貓氏] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu)

? ? def make_old_cake(self):
????????Master.__init__(self)
????????Master.make_cake(self)

? ? def make_new_cake(self):
????????School.__init__(self)
????????School.make_cake(self)

class PrenticePrentice(Prentice):
????pass

damao = Prentice()
# 對(duì)象不能訪問私有權(quán)限的屬性和方法
print(damao.__money)
damao.__print_info()
# 可以通過訪問公有方法set_money()來修改私有屬性的值
damao.set_money(100)
# 可以通過訪問公有方法get_money()來獲取私有屬性的值
print(damao.get_money())

3. 多態(tài)

所謂多態(tài):定義時(shí)的類型和運(yùn)行時(shí)的類型不一樣普筹,此時(shí)就成為多態(tài) 败明,多態(tài)的概念是應(yīng)用于Java和C#這一類強(qiáng)類型語言中,而Python崇尚“鴨子類型”太防。

> 鴨子類型:雖然我想要一只"鴨子"妻顶,但是你給了我一只鳥。 但是只要這只鳥走路像鴨子蜒车,叫起來像鴨子讳嘱,游泳也像鴨子,我就認(rèn)為這是鴨子酿愧。

Python的多態(tài)沥潭,就是弱化類型,重點(diǎn)在于對(duì)象參數(shù)是否有指定的屬性和方法嬉挡,如果有就認(rèn)定合適钝鸽,而不關(guān)心對(duì)象的類型是否正確。

- Python偽代碼實(shí)現(xiàn)Java或C#的多態(tài)

class F1(object):
????def show(self):
????????print('F1.show')

class S1(F1):
????def show(self):
????????print('S1.show')

class S2(F1):
????def show(self):
????????print('S2.show')

# 由于在Java或C#中定義函數(shù)參數(shù)時(shí)庞钢,必須指定參數(shù)的類型
# 為了讓Func函數(shù)既可以執(zhí)行S1對(duì)象的show方法拔恰,又可以執(zhí)行S2對(duì)象的show方法,
# 所以在def Func的形參中obj的類型是 S1和S2的父類即F1
# 而實(shí)際傳入的參數(shù)是:S1對(duì)象和S2對(duì)象

def Func(F1 obj): 這是java的寫法基括,Python應(yīng)該是def Func(object)
? ? """Func函數(shù)需要接收一個(gè)F1類型或者F1子類的類型"""
? ?print(obj.show())

#當(dāng)看到形參是object的函數(shù)時(shí)颜懊,可理解為這個(gè)函數(shù)可以接收所有對(duì)象

s1_obj = S1()
Func(s1_obj) # 在Func函數(shù)中傳入S1類的對(duì)象 s1_obj,執(zhí)行 S1 的show方法风皿,結(jié)果:S1.show
s2_obj = S2()
Func(s2_obj) # 在Func函數(shù)中傳入Ss類的對(duì)象 ss_obj河爹,執(zhí)行 Ss 的show方法,結(jié)果:S2.show

>? 通俗點(diǎn)理解:定義obj這個(gè)變量是說的類型是:F1的類型桐款,但是在真正調(diào)用Func函數(shù)時(shí)給其傳遞的不一定是F1類的實(shí)例對(duì)象咸这,有可能是其子類的實(shí)例對(duì)象, 這種情況就是所謂的多態(tài)

>??python是弱類型鲁僚,即無論傳遞過來的是什么腻贰,obj變量都能夠指向它肪虎,這也就沒有所謂的多態(tài)了(弱化了這個(gè)概念)

4. 類屬性和實(shí)例屬性

在前面的例子中我們接觸到的就是實(shí)例屬性(對(duì)象屬性),顧名思義,類屬性就是`類對(duì)象`所擁有的屬性虏肾,它被所有`類對(duì)象`的`實(shí)例對(duì)象`所共有,在內(nèi)存中只存在一個(gè)副本聪姿,這個(gè)和C++中類的靜態(tài)成員變量有點(diǎn)類似算芯。對(duì)于公有的類屬性,在類外可以通過`類對(duì)象`和`實(shí)例對(duì)象`訪問

類屬性

class People(object):
????name = 'Tom'? # 公有的類屬性
????__age = 12? # 私有的類屬性

p = People()
print(p.name)? # 正確
print(People.name)? # 正確
print(p.__age)? # 錯(cuò)誤侥啤,不能在類外通過實(shí)例對(duì)象訪問私有的類屬性
print(People.__age) # 錯(cuò)誤当叭,不能在類外通過類對(duì)象訪問私有的類屬性

實(shí)例屬性(對(duì)象屬性)

class People(object):
????address = '山東'? # 類屬性
????def __init__(self):
????????self.name = 'xiaowang'? # 實(shí)例屬性
????????self.age = 20? # 實(shí)例屬性

p = People()
p.age = 12? # 實(shí)例屬性
print(p.address)? # 正確
print(p.name)? # 正確
print(p.age)? # 正確
print(People.address)? # 正確
print(People.name)? # 錯(cuò)誤
print(People.age)? # 錯(cuò)誤

不能通過實(shí)例(對(duì)象)去修改類屬性,要通過類改變類屬性

class People(object):
????country = 'china' #類屬性

print(People.country)
p = People()
print(p.country)
p.country = 'japan' # 這是錯(cuò)誤的做法盖灸,不能實(shí)際改變類屬性蚁鳖,要通過類改變類屬性
print(p.country)? # 實(shí)例屬性會(huì)屏蔽掉同名的類屬性,打印p.country會(huì)使japan
print(People.country)# 此時(shí)打印People.country 仍然是china
del p.country? # 刪除實(shí)例屬性
print(p.country)

總結(jié)

- 如果需要在類外修改`類屬性`赁炎,必須通過`類對(duì)象`去引用然后進(jìn)行修改醉箕。如果通過實(shí)例對(duì)象去引用,會(huì)產(chǎn)生一個(gè)同名的`實(shí)例屬性`徙垫,這種方式修改的是`實(shí)例屬性`讥裤,不會(huì)影響到`類屬性`,并且之后如果通過實(shí)例對(duì)象去引用該名稱的屬性姻报,實(shí)例屬性會(huì)強(qiáng)制屏蔽掉類屬性己英,即引用的是`實(shí)例屬性`,除非刪除了該`實(shí)例屬性`吴旋。

5.? 靜態(tài)方法和類方法

1)? 類方法

是類對(duì)象所擁有的方法损肛,需要用修飾器`@classmethod`來標(biāo)識(shí)其為類方法,對(duì)于類方法荣瑟,第一個(gè)參數(shù)必須是類對(duì)象荧关,一般以`cls`作為第一個(gè)參數(shù)(當(dāng)然可以用其他名稱的變量作為其第一個(gè)參數(shù),但是大部分人都習(xí)慣以'cls'作為第一個(gè)參數(shù)的名字褂傀,就最好用'cls'了)忍啤,能夠通過實(shí)例對(duì)象和類對(duì)象去訪問。

class People(object):
????country = 'china'
????#類方法仙辟,用classmethod來進(jìn)行修飾
????@classmethod
????def get_country(cls): —— cls的意思就是當(dāng)前類
????????return cls.country

p = People()
print(p.get_country())? ? #可以用過實(shí)例對(duì)象引用
print(People.get_country())? ? #可以通過類對(duì)象引用

類方法還有一個(gè)用途就是可以對(duì)類屬性進(jìn)行修改:

class People(object):
????country = 'china'
????#類方法同波,用classmethod來進(jìn)行修飾
????@classmethod
????def get_country(cls):
????????return cls.country

? ? @classmethod
????def set_country(cls,country):
????????cls.country = country

p = People()
print(p.get_country())? #可以用過實(shí)例對(duì)象訪問
print(People.get_country())? ? #可以通過類訪問
p.set_country('japan')
print(p.get_country())
print(People.get_country())

結(jié)果顯示在用類方法對(duì)類屬性修改之后,通過類對(duì)象和實(shí)例對(duì)象訪問都發(fā)生了改變

2*)? 靜態(tài)方法

需要通過修飾器`@staticmethod`來進(jìn)行修飾叠国,靜態(tài)方法不需要多定義參數(shù)未檩,可以通過對(duì)象和類來訪問。

class People(object):
????country = 'china'
????@staticmethod
????#靜態(tài)方法
????def get_country():
????????return People.country

p = People()
# 通過對(duì)象訪問靜態(tài)方法
p.get_contry()
# 通過類訪問靜態(tài)方法
print(People.get_country())

總結(jié)

1. 從類方法和實(shí)例方法以及靜態(tài)方法的定義形式就可以看出來粟焊,類方法的第一個(gè)參數(shù)是類對(duì)象cls冤狡,那么通過cls引用的必定是類對(duì)象的屬性和方法孙蒙;

2. 實(shí)例方法的第一個(gè)參數(shù)是實(shí)例對(duì)象self,那么通過self引用的可能是類屬性悲雳、也有可能是實(shí)例屬性(這個(gè)需要具體分析)挎峦,不過在存在相同名稱的類屬性和實(shí)例屬性的情況下,實(shí)例屬性優(yōu)先級(jí)更高合瓢。

3. 靜態(tài)方法中不需要額外定義參數(shù)坦胶,因此在靜態(tài)方法中引用類屬性的話,必須通過類實(shí)例對(duì)象來引用晴楔,靜態(tài)方法內(nèi)存空間是一直占用顿苇,只用項(xiàng)目代碼走完才會(huì)釋放,而其他方法在用完這個(gè)方法以后就會(huì)釋放
classPeople(object):
????country = 'china'
?????@staticmethod
?????def getCountry():
?????????return People.country

python中的方法總結(jié):
1.實(shí)例方法(對(duì)象方法) --> 場(chǎng)景很多

????調(diào)用格式: 對(duì)象名.實(shí)例方法名()
????使用場(chǎng)景: 在方法中需要self
2.類方法 --> 對(duì)私有類屬性取值或者賦值
????定義格式: @classmethod
????????????????????def 類方法名(cls):
????調(diào)用格式: 類名.類方法名()? 或者 對(duì)象名.類方法名()
????使用場(chǎng)景: 在方法中需要cls類名
3.靜態(tài)方法 --> 一般不用
????定義格式: @staticmethod
????????????????????def 靜態(tài)方法名():
????調(diào)用格式: 類名.類方法名() 或者 對(duì)象名.類方法名()
????使用場(chǎng)景: 在方法中不需要self 也不需要cls? ? ?

6. `__new__`方法

`__new__和__init__`的作用:

class A(object):
????def __new__(cls):????????
????????print("這是 new 方法")????????
????????return object.__new__(cls)
????def __init__(self):
????????print("這是 init 方法")

A()

總結(jié):new在ini之前創(chuàng)建一個(gè)對(duì)象

- `__new__`至少要有一個(gè)參數(shù)cls税弃,代表要實(shí)例化的類纪岁,此參數(shù)在實(shí)例化時(shí)由Python解釋器自動(dòng)提供
- `__new__`必須要有返回值,返回實(shí)例化出來的實(shí)例则果,這點(diǎn)在自己實(shí)現(xiàn)`__new__`時(shí)要特別注意蜂科,可以return父類`__new__`出來的實(shí)例,或者直接是object的`__new__`出來的實(shí)例
- `__init__`有一個(gè)參數(shù)self短条,就是這個(gè)`__new__`返回的實(shí)例导匣,`__init__`在`__new__`的基礎(chǔ)上可以完成一些其它初始化的動(dòng)作,`__init__`不需要返回值
- 我們可以將類比作制造商茸时,`__new__`方法就是前期的原材料購買環(huán)節(jié)贡定,`__init__`方法就是在有原材料的基礎(chǔ)上,加工可都,初始化商品環(huán)節(jié)

補(bǔ)充:?*args:? 表示? 將位置參數(shù)中的剩余實(shí)參存放到 args 中, 且以元組的形式保存

def foo(x,*args):
????print(x)
????print(args)
foo(1,2,3,4,5)#其中的2,3,4,5都給了args

運(yùn)行結(jié)果:
1
(2, 3, 4, 5)

def foo(x,y=1,*args): # *args一定要在缺省參數(shù)以后
????print(x)
????print(y)
????print(args)
foo(1,2,3,4,5)#其中的x為1缓待,y=1的值被2重置了,3,4,5都給了args

結(jié)果:
1
2
(3, 4, 5)

def foo(x,*args,y=1):
????print(x)
????print(args)
????print(y)
foo(1,2,3,4,5)#其中的x為1渠牲,2,3,4,5都給了args,y按照默認(rèn)參數(shù)依舊為1

結(jié)果:
1
(2, 3, 4, 5)
1

** kwargs: 表示? 形參中按照關(guān)鍵字傳值 把多余的值以字典呈現(xiàn)
def foo(x,**kwargs):
? ? print(x)
????print(kwargs)
foo(1,y=1,a=2,b=3,c=4)#將y=1,a=2,b=3,c=4以字典的方式給了kwargs

執(zhí)行結(jié)果是:
1
{'y': 1, 'a': 2, 'b': 3, 'c': 4}

def foo(x,*args,**kwargs):
????print(x)
????print(args)
????print(kwargs)
foo(1,2,3,4,y=1,a=2,b=3,c=4)
#將1傳給了x旋炒,將2,3,4以元組方式傳給了args,y=1,a=2,b=3,c=4以字典的方式給了kwargs

結(jié)果:
1
(2, 3, 4)
{'y': 1, 'a': 2, 'b': 3, 'c': 4}

位置參數(shù)签杈、默認(rèn)參數(shù)瘫镇、**kwargs三者的順序必須是位置參數(shù)、默認(rèn)參數(shù)答姥、**kwargs铣除,不然就會(huì)報(bào)錯(cuò):
def foo(x,y=1,**kwargs):
????print(x)
????print(y)
????print(kwargs)
foo(1,a=2,b=3,c=4)#將1按照位置傳值給x,y按照默認(rèn)參數(shù)為1鹦付,a=2,b=3,c=4以字典的方式給了kwargs

結(jié)果:
1
1
{'a': 2, 'b': 3, 'c': 4}

7*? 單例模式

1. 單例是什么

舉個(gè)常見的單例模式例子尚粘,我們?nèi)粘J褂玫碾娔X上都有一個(gè)回收站,在整個(gè)操作系統(tǒng)中敲长,回收站只能有一個(gè)實(shí)例郎嫁,整個(gè)系統(tǒng)都使用這個(gè)唯一的實(shí)例秉继,而且回收站自行提供自己的實(shí)例。因此回收站是單例模式的應(yīng)用泽铛。
確保某一個(gè)類只有一個(gè)實(shí)例尚辑,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,這個(gè)類稱為單例類厚宰,單例模式是一種對(duì)象創(chuàng)建型模式腌巾。

2. 創(chuàng)建單例-保證只有1個(gè)對(duì)象

# 單例模式: 在程序中這個(gè)類創(chuàng)建出來的對(duì)象 只有一個(gè)(也就是占用一分內(nèi)存地址)
# 單例模式 也只會(huì)走一次__init__方法(保證這個(gè)單例對(duì)象的屬性也是唯一的)(name=小明
#? age = 20)
# 合理使用內(nèi)存 避免浪費(fèi)(避免浪費(fèi)內(nèi)存)

class Person(object):
????# 定義一個(gè)私有類屬性, 初始化是該類為None
????__instance = None
????def __new__(cls, *args, **kwargs):
????????# 如果不存在, 則進(jìn)入if語句
????????if not cls.__instance:
????????????# 不存在時(shí)進(jìn)入? 我們就創(chuàng)建一個(gè)
????????????cls.__instance = object.__new__(cls)
????????# 創(chuàng)建出來之后, return返回
????????return cls.__instance

# 創(chuàng)建對(duì)象遂填,類里面的方法是引用哪個(gè)方法铲觉,走哪個(gè),不會(huì)每次都從頭開始走
xiaoming = Person('小明', 20)
xiaohong = Person('小紅', 32)
xiaozhang = Person('小孫', 31)
print(xiaoming)
print(xiaohong)
print(xiaozhang)

運(yùn)行結(jié)果:
# 我們可以看到三個(gè)值都是一樣的,代表對(duì)象沒有創(chuàng)建多個(gè),而是只有一個(gè),達(dá)到我們的目的
<__main__.Person object at 0x00000000023CD2E8>
<__main__.Person object at 0x00000000023CD2E8>
<__main__.Person object at 0x00000000023CD2E8>

3. 創(chuàng)建單例-保證只執(zhí)行1次__init__方法

class Person(object):
????__instance = None
????# 創(chuàng)建一個(gè)私有類屬性, 記錄是否是第一次進(jìn)入
????# 只有第一次進(jìn)入的時(shí)候, 當(dāng)前初始化的值(True)被使用
????# 其他時(shí)候進(jìn)入的都將該參數(shù)變?yōu)镕alse
????__isFirst = True
????def __new__(cls, *args, **kwargs):
????????if not cls.__instance:
????????????cls.__instance = object.__new__(cls)
????????return cls.__instance

????# 對(duì)init方法加工, 使其只能被調(diào)用一次, 保證對(duì)象的屬性只能賦值一次
????def __init__(self, name, age):
????????if Person.__isFirst:
????????????self.name = name
????????????self.age = age
????????????Person.__isFirst = False

# 創(chuàng)建對(duì)象
xiaoming = Person('小明', 20)
xiaohong = Person('小紅', 32)
xiaozhang = Person('小孫', 31)
print(xiaoming)
print(xiaohong)
print(xiaozhang)
print(xiaozhang.name, xiaoming.name, xiaohong.name)

運(yùn)行結(jié)果:
<__main__.Person object at 0x00000000023CD2E8>
<__main__.Person object at 0x00000000023CD2E8>
<__main__.Person object at 0x00000000023CD2E8>
小明 小明 小明

總結(jié):

- 單例: 單獨(dú)的實(shí)例,? 即只能有一個(gè)實(shí)例

- 這樣可以節(jié)約內(nèi)存,? 例如針對(duì)公共的一些對(duì)象,我們只需要指定一個(gè)即可, 需要使用時(shí), 直接拿去用.

- 內(nèi)存有限, 請(qǐng)珍惜.

- 既然該類的對(duì)象都只有一個(gè), 那么該對(duì)象的屬性也只有一份, 不存在別人也有該對(duì)象屬性的情況.

九.? 異常 & 模塊(了解)

1.? 異常

看如下示例:
????print '-----test--1---'
????open('123.txt','r')
????print '-----test--2---'

運(yùn)行結(jié)果:
-----test--1---
Traceback (most recent call last):
File "demo.py", line 2, in <module>
????open('123.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: '123.txt'

說明:

>? 打開一個(gè)不存在的文件123.txt吓坚,當(dāng)找不到123.txt 文件時(shí)撵幽,就會(huì)拋出給我們一個(gè)IOError類型的錯(cuò)誤,No such file or directory:123.txt (沒有123.txt這樣的文件或目錄)

> 當(dāng)Python檢測(cè)到一個(gè)錯(cuò)誤時(shí)礁击,解釋器就無法繼續(xù)執(zhí)行了盐杂,反而出現(xiàn)了一些錯(cuò)誤的提示,這就是所謂的"異常"

2.? 捕獲異常

1)? 單個(gè)異常捕獲(try...except...)

使用規(guī)則:
try:
????可能發(fā)生異常的代碼01
????可能發(fā)生異常的代碼02
????...
except 要捕獲的異常類型名:
????如果發(fā)生異常,進(jìn)行的后續(xù)處理01
????如果發(fā)生異常,進(jìn)行的后續(xù)處理02
????...

看如下示例:
try:
????print(num)
except NameError:
????print('發(fā)生異常了')
print('go on continue')

運(yùn)行結(jié)果:
發(fā)生異常了
go on continue

說明:

- 如果我們?cè)诳赡馨l(fā)生異常的代碼外, 添加 try....except.... 方法, 這樣就可以捕獲發(fā)生的異常,可以對(duì)異常進(jìn)行實(shí)時(shí)跟蹤, 而且程序不會(huì)崩潰, 可以繼續(xù)運(yùn)行后續(xù)的代碼
- 我們通過運(yùn)行結(jié)果可以看到, 雖然異常發(fā)生了, 但是對(duì)程序的破壞性不是很大, 有利于程序的繼續(xù)執(zhí)行.
- 其中, try:? 里面的代碼是有可能發(fā)生異常的內(nèi)容
- except? 后面緊跟的是發(fā)生異常的類型名稱, 如果異常名稱弄錯(cuò), 那么當(dāng)前異常照樣捕獲不到, 就相當(dāng)于:? except? 鴨子類型異常:? ? 但是發(fā)生的是天鵝類型異常,? 這樣的話except照樣捕獲不到該異常.
- 使用try...except...能夠使我們?cè)诋惓0l(fā)生的情況下正常執(zhí)行程序, 這一點(diǎn)非常非常好. 對(duì)于公司來說,這個(gè)功能非常有用.

2) 多種異常捕獲

使用 except 捕獲多種異常
使用規(guī)則:
try:
????可能發(fā)生異常的代碼01
????可能發(fā)生異常的代碼02
????...
except (要捕獲的異常類型名01,要捕獲的異常類型名02, 要捕獲的異常類型名03...):
????如果發(fā)生異常,進(jìn)行的后續(xù)處理01
????如果發(fā)生異常,進(jìn)行的后續(xù)處理02
????...

例如:
try:
????print(num)
????open('hm.txt')
except (FileNotFoundError, NameError):
????print('捕獲到異常了')

運(yùn)行結(jié)果:
捕獲到異常了

說明:
* except后面可以跟 多種類型的異常名, 并且把這些異常名用元組包裹起來, 就可以同時(shí)捕獲多種異常.
* 其他使用方式不變

3) 異常的描述信息獲取

總結(jié):
* except 后面可以用括號(hào)包含多種異常的名字
* except后面可以連接 as 關(guān)鍵字, as 關(guān)鍵字能夠把異常信息賦給一個(gè)變量, 我們可以通過打印變量的形式來獲取有關(guān)該異常的描述信息
* 我們也可以簡(jiǎn)單的理解為:? as 關(guān)鍵字? 能夠把異常描述信息 保存在變量中.

4)? 捕獲所有異常

我們有兩種方式可以捕獲所有的異常:
第一種 :
使用規(guī)則:
try:
有可能產(chǎn)生異常的代碼01
有可能產(chǎn)生異常的代碼02
..
except:
????捕獲到異常后的操作01
? ? 捕獲到異常后的操作02
? ? ...

> 說明: 雖然用這樣的形式可以捕獲異常,但是不建議大家使用, 原因是這樣的方式獲取的異常不能夠查看? ? 聚的異常信息.?

第二種 :
使用規(guī)則:
try:
????有可能產(chǎn)生異常的代碼01
????有可能產(chǎn)生異常的代碼02
????...
except Exception:
????捕獲到異常后的操作01
????捕獲到異常后的操作02
????...

> 說明:
> * 使用這樣的形式可以捕獲所有類型的異常, 原因是: Exception是所有異常類的父類.
> * 這樣的書寫形式后面可以跟 as 關(guān)鍵字, 從而可以存儲(chǔ)并打印輸出異常的具體信息.
> * 推薦使用這樣的形式, 當(dāng)然, 如果你不需要異常信息, 只想知道代碼是否有異常, 可以使用上面的形式

舉例:
try:
????open('hm.txt','r')
except:
????print('獲取異常...')

運(yùn)行結(jié)果:
獲取異常...

try:
????print(num)
????open('hm.txt')
except Exception as info:
????print('捕獲到異常了', info)

運(yùn)行結(jié)果:
捕獲到異常了 name 'num' is not defined

> **注意**:
> 上面代碼中: 因?yàn)楫惓4a有兩行, 所以捕獲到的是先執(zhí)行的第 2 行的異常.

總結(jié):
* 捕獲所有異常和正常的捕獲行為很像, 只是捕獲類名有所變化
* 此處學(xué)習(xí)捕獲所有異常后, 在公司如無其他需求, 一般都是使用上面的兩種方法, 獲取代碼的異常.
* 此處學(xué)習(xí)的兩種方法均可使用, 希望大家牢記, 多多聯(lián)系.

5)? 與else的搭配使用

> 在 if 中哆窿,它的作用是當(dāng)條件不滿足時(shí)執(zhí)行的代碼链烈;
> 同樣在 try...except...else 中也是如此,即如果沒有捕獲到異常挚躯,那么就執(zhí)行else中的事情
> 如果產(chǎn)生異常, 就不執(zhí)行 else 中的語句.

try:
????num = 100
????print(num)
except NameError as errorMsg:
????print('產(chǎn)生錯(cuò)誤了:%s'%errorMsg)
else:
????print('沒有捕獲到異常强衡,真高興')

運(yùn)行結(jié)果如下:
100
沒有捕獲到異常,真高興

try:
????# num = 100
????print(num)
except NameError as errorMsg:
????print('產(chǎn)生錯(cuò)誤了:%s'%errorMsg)
else:
????print('沒有捕獲到異常码荔,真高興')

運(yùn)行結(jié)果如下:
產(chǎn)生錯(cuò)誤了:name 'num' is not defined

6)? 與finally的搭配

finally語句用來表達(dá)這樣的情況:
> 在程序中漩勤,如果一個(gè)段代碼必須要執(zhí)行,即無論異常是否產(chǎn)生都要執(zhí)行缩搅,那么此時(shí)就需要使用finally越败。 比如文件關(guān)閉,釋放鎖硼瓣,把數(shù)據(jù)庫連接返還給連接池等

try:
????num = 100
????print(num)
except NameError as errorMsg:
????print('產(chǎn)生錯(cuò)誤了:%s'%errorMsg)
finally:
????print('finally方法')

結(jié)果:
100
finally方法

try:
????# num = 100
????print(num)
except NameError as errorMsg:
????print('產(chǎn)生錯(cuò)誤了:%s'%errorMsg)
finally:
????print('finally方法')

結(jié)果:
產(chǎn)生錯(cuò)誤了:name 'num' is not defined
finally方法

總結(jié):
* finally 如果添加了, 那么無論是否發(fā)生異常,? finally里面的程序都會(huì)執(zhí)行
* finally一般不寫, 除非公司有這方面的需求.
* finally 和 try.... except.... 可以搭配使用, 組成:? try.... except.... finally.....
* 其中,? try 中出錯(cuò), 那么執(zhí)行 except 和 finally 的代碼
* 如果,? try? 中沒有錯(cuò)誤, 那么執(zhí)行? try? 和 finally 中的代碼
*? finally 和 try .... except... else .... 可以搭配使用, 組成 try.....except....else.....finally....
* 其中, 如果 try 中出錯(cuò), 那么執(zhí)行 except? 和 finally 的代碼
* 如果, try 中如果沒有錯(cuò)誤, 那么執(zhí)行? try 和 else 和 finally 的代碼

? try:
????num = 100
????print(num)
except NameError as errorMsg:
????print('產(chǎn)生錯(cuò)誤了:%s'%errorMsg)
else:
????print('else')
finally:
????print('finally方法')

結(jié)果:
100
else
finally方法

* 如果出錯(cuò),則:
try:
????# num = 100
????print(num)
except NameError as errorMsg:
????print('產(chǎn)生錯(cuò)誤了:%s'%errorMsg)
else:
????print('else')
finally:
????print('finally方法')

結(jié)果:
產(chǎn)生錯(cuò)誤了:name 'num' is not defined
finally方法

7)? 異常的傳遞

try嵌套

> 兩個(gè)try嵌套, 如果內(nèi)部的異常沒有捕獲到, 則異常會(huì)往外部傳遞, 外部會(huì)進(jìn)行捕獲:

try:
????num = 100
????print(num)
????try:
????????open('text.haha')
????except NameError as error:
????????print('嵌套內(nèi)部的異常捕獲:', error)
except Exception as result:
????print('嵌套外圍的異常捕獲: 產(chǎn)生錯(cuò)誤了', result)

運(yùn)行結(jié)果:
100
嵌套外圍的異常捕獲: 產(chǎn)生錯(cuò)誤了 [Errno 2] No such file or directory: 'text.haha'

說明:

上例中,內(nèi)部沒有捕獲到的原因是:? open()方法出錯(cuò)的異常類型應(yīng)該是IOName, 而內(nèi)部我們捕獲的類型是NameError.

> 兩個(gè)try嵌套, 如果內(nèi)部的異常, 內(nèi)部已經(jīng)捕獲到, 則不會(huì)往外部傳遞, 外部不會(huì)捕獲:

try:
????num = 100
????print(num)
????try:
????????open('text.haha')
? ? except Exception as error:
????????print('嵌套內(nèi)部的異常捕獲:', error)
except Exception as result:
????print('嵌套外圍的異常捕獲: 產(chǎn)生錯(cuò)誤了', result)

運(yùn)行結(jié)果:
100
嵌套內(nèi)部的異常捕獲: [Errno 2] No such file or directory: 'text.haha'

**說明**:

? 這次內(nèi)部能夠捕獲異常的原因是: 內(nèi)部捕獲的是所有的異常類型,使用的是: Exception.

函數(shù)嵌套

def demo1():

? ? print("----demo1-1----")

? ? print(num)

? ? print("----demo1-2----")

def demo2():

? ? try:

? ? ? ? print("----demo2-1----")

? ? ? ? demo1()

? ? ? ? print("----demo2-2----")

? ? except Exception as result:

? ? ? ? print("捕獲到了異常究飞,信息是:%s" % result)

? ? print("----demo2-3----")

demo2()

運(yùn)行結(jié)果:

----demo2-1----

----demo1-1----

捕獲到了異常,信息是:name 'num' is not defined

----demo2-3----

或者:

def demo1():

? ? print("----demo1-1----")

? ? try:

? ? ? ? print(num)

? ? ? ? print("----demo1-2----")

? ? except Exception as result:

? ? ? ? print("捕獲到了異常堂鲤,信息是:%s" % result)

? ? print("----demo1-3----")

def demo2():

? ? print("----demo2-1----")

? ? demo1()

? ? print("----demo2-2----")

demo2()

結(jié)果:

----demo2-1----

----demo1-1----

捕獲到了異常噪猾,信息是:name 'num' is not defined

----demo1-3----

----demo2-2----

**總結(jié)**:

* 如果try嵌套,那么如果里面的try沒有捕獲到這個(gè)異常筑累,那么外面的try會(huì)接收到這個(gè)異常袱蜡,然后進(jìn)行處理,如果外邊的try依然沒有捕獲到慢宗,那么再往外進(jìn)行傳遞坪蚁。奔穿。。
* 如果異常是在函數(shù)嵌套中產(chǎn)生的:
* 例如函數(shù)A---->函數(shù)B---->函數(shù)C,而異常是在函數(shù)C中產(chǎn)生的敏晤,那么如果函數(shù)C中沒有對(duì)這個(gè)異常進(jìn)行處理贱田,那么這個(gè)異常會(huì)傳遞到函數(shù)B中,如果函數(shù)B有異常處理那么就會(huì)按照函數(shù)B的處理方式進(jìn)行執(zhí)行嘴脾;如果函數(shù)B也沒有異常處理男摧,那么這個(gè)異常會(huì)繼續(xù)傳遞,以此類推译打。耗拓。。如果所有的函數(shù)都沒有處理奏司,那么此時(shí)就會(huì)進(jìn)行異常的默認(rèn)處理乔询,程序最終會(huì)崩潰.
* 第一個(gè)案例中:? 當(dāng)demo1中發(fā)生了異常, 此異常被傳遞到demo2函數(shù)中處理,當(dāng)處理完成后, 并沒有返回demo1中進(jìn)行執(zhí)行, 而是在demo2中繼續(xù)執(zhí)行.

3.? 模塊

1). Python中的模塊

>? 在Python中有一個(gè)概念叫做模塊(module),這個(gè)和C語言中的頭文件以及Java中的包很類似韵洋,比如在Python中要調(diào)用`randint()函數(shù)`竿刁,必須用import關(guān)鍵字引入 random 這個(gè)模塊,下面就來了解一下Python中的模塊搪缨。

> 模塊就好比是工具包食拜,要想使用這個(gè)工具包中的工具(就好比函數(shù)),就需要導(dǎo)入這個(gè)模塊

2)? import

>? 在Python中,? 一般用關(guān)鍵字`import`來導(dǎo)入模塊

>? 比如要引用模塊 random副编,就可以在文件最開始的地方用 import random 來導(dǎo)入负甸。

形如:

import module1,mudule2...

當(dāng)解釋器遇到 import 語句,我們添加的模塊就會(huì)被導(dǎo)入齿桃。

在調(diào)用 random 模塊中的函數(shù)時(shí)惑惶,必須這樣引用:

模塊名.函數(shù)名

例如:

random.randint()

> 因?yàn)榭赡艽嬖谠诙鄠€(gè)模塊中含有相同名稱的函數(shù),此時(shí)如果只是通過函數(shù)名來調(diào)用短纵,解釋器無法知道到底要調(diào)用哪個(gè)函數(shù)带污。所以如果像上述這樣引入模塊的時(shí)候,調(diào)用函數(shù)必須加上模塊名

? ? import math

? ? # 這樣會(huì)報(bào)錯(cuò)

? ? # 求4的非負(fù)平方根

? ? print sqrt(4)

? ? #這樣才能正確輸出結(jié)果

? ? print math.sqrt(4)

3)? from…import

有時(shí)候我們只需要用到模塊中的某些個(gè)函數(shù)香到,只需要引入該函數(shù)即可鱼冀,此時(shí)可以用下面方法實(shí)現(xiàn):

from 模塊名 import 函數(shù)名1,函數(shù)名2....

不僅可以引入函數(shù),還可以引入一些全局變量悠就、類等

**注意**:

> - 通過這種方式引入的時(shí)候千绪,調(diào)用函數(shù)時(shí)只能給出函數(shù)名,不能給出模塊名梗脾,但是當(dāng)兩個(gè)模塊中含有相同名稱函數(shù)的時(shí)候荸型,后面一次引入會(huì)覆蓋前一次引入。也就是說假如模塊A中有函數(shù)function( )炸茧,在模塊B中也有函數(shù)function( )瑞妇,如果引入A中的function在先稿静、B中的function在后,那么當(dāng)調(diào)用function函數(shù)的時(shí)候辕狰,是去執(zhí)行模塊B中的function函數(shù)改备。

> - 如果想一次性引入某個(gè)模塊中所有的東西,還可以通過 from 模塊名 import * 來實(shí)現(xiàn)

例如蔓倍,要導(dǎo)入模塊 random 的 randint 方法悬钳,使用如下語句:

? ? from random import randint

**注意**:

- 這樣的方式不會(huì)把整個(gè)模塊的內(nèi)容導(dǎo)入到當(dāng)前文件中,? 它只會(huì)將模塊中的單個(gè)方法引入進(jìn)來

4). from … import *

把一個(gè)模塊的所有內(nèi)容全都導(dǎo)入到當(dāng)前的文件中也是可行的,只需使用如下聲明:

from 模塊名 import *

**注意**:

- 這提供了一個(gè)簡(jiǎn)單的方法來導(dǎo)入一個(gè)模塊中的所有項(xiàng)目偶翅。然而這種聲明不該被過多地使用默勾。

- 這個(gè)方法最好不要用的太多, 因?yàn)檫@樣的方式是把模塊中的內(nèi)容一次性都引入, 會(huì)對(duì)內(nèi)存造成很大的壓力.

5). as

> as 關(guān)鍵字可以給導(dǎo)入的模塊起一個(gè)別名

使用格式:import 模塊名 as 別名

說明:

* 需要說明的是 一旦使用 as 給某個(gè)模塊起別名以后, 原來模塊的名字就不可以使用了, 用了會(huì)報(bào)錯(cuò)

import random as tt

tt.randint(0, 10)

random.randint(0, 10)

運(yùn)行結(jié)果為:

Traceback (most recent call last):

? File "demo.py", line 3, in <module>

? ? random.randint(0, 10)

NameError: name 'random' is not defined

6). 定位模塊? (linux系統(tǒng))

當(dāng)你導(dǎo)入一個(gè)模塊,Python解析器對(duì)模塊位置的搜索順序是:

-. 當(dāng)前目錄

-. 如果不在當(dāng)前目錄倒堕,Python則搜索在shell變量PYTHONPATH下的每個(gè)目錄灾测。

-. 如果都找不到爆价,Python會(huì)察看默認(rèn)路徑垦巴。UNIX下,默認(rèn)路徑一般為/usr/local/lib/python/

-. 模塊搜索路徑存儲(chǔ)在system模塊的sys.path變量中铭段。變量里包含當(dāng)前目錄骤宣,PYTHONPATH和由安裝過程決定的默認(rèn)目錄。

7). 模塊制作

-定義自己的模塊

> 在Python中序愚,每個(gè)Python文件都可以作為一個(gè)模塊憔披,模塊的名字就是文件的名字。

> 比如有這樣一個(gè)文件 demo.py爸吮,在 demo.py 中定義了函數(shù)add

# demo.py文件中:

def add(a, b):

? ? return a + b

- 調(diào)用自己定義的模塊

>? 那么在其他文件中就可以先import demo芬膝,然后通過demo.add(a,b)來調(diào)用了,當(dāng)然也可以通過from demo import add來引入

main.py文件中:

# main.py

import demo

result = demo.add(11,22)

print(result)

-. 測(cè)試模塊

>? 在實(shí)際開中形娇,當(dāng)一個(gè)開發(fā)人員編寫完代碼后锰霜,會(huì)檢測(cè)這個(gè)模塊是否達(dá)到了想要的效果, 往往會(huì)在當(dāng)前項(xiàng)目中添加一些檢測(cè)代碼, 例如:

demo.py文件中:

# demo.py文件中

def add(a,b):

? ? return a+b

# 用來進(jìn)行自測(cè):

ret = add(12,22)

print('demo:? 12+22=%d'%ret)

如果此時(shí),在其他py文件中引入了此文件的話桐早,想想看癣缅,測(cè)試的那段代碼是否也會(huì)執(zhí)行呢!

main.py文件中:

import demo

result = demo.add(11,22)

print(result)

運(yùn)行現(xiàn)象:

demo:? 12+22=34

33

至此哄酝,可發(fā)現(xiàn) demo.py 中的測(cè)試代碼友存,應(yīng)該是單獨(dú)執(zhí)行 demo.py 文件時(shí)才應(yīng)該執(zhí)行的,不應(yīng)該是其他的文件中引用而執(zhí)行

為了解決這個(gè)問題陶衅,python在執(zhí)行一個(gè)文件時(shí)有個(gè)變量`__name__`

##### demo.py文件中運(yùn)行的結(jié)果為:

# demo.py文件中

def add(a,b):

? ? return a+b

# 用來進(jìn)行自測(cè):

print('demo中__name__的值是: %s' % __name__)

結(jié)果:

demo中__name__的值是: __main__

在別的文件中導(dǎo)入demo.py文件,然后運(yùn)行:

在main.py文件中運(yùn)行后:

import demo

運(yùn)行結(jié)果:

demo中__name__的值是: demo

# 所以在demo.py文件中屡立,自測(cè)一般先判斷: if __name__ == '__main__':

def add(a,b):

? ? return a+b

# 用來進(jìn)行自測(cè):

def main():

? ? print(add(10,20))

if __name__ == '__main__':

????main()

?總結(jié):

- 可以根據(jù)__name__變量的結(jié)果能夠判斷出,是直接執(zhí)行的python腳本還是被引入執(zhí)行的搀军,從而能夠有選擇性的執(zhí)行測(cè)試代碼

8).模塊中的`__all__`

我們可以在模塊中添加`__all__`屬性.? 這個(gè)屬性的作用是:

> 如果一個(gè)模塊中有`__all__`屬性膨俐,則只有`__all__`內(nèi)指定的屬性, 方法, 類可被導(dǎo)入

> 但是這樣做有一個(gè)限制:? 必須用 from 模塊名 import *? 的形式導(dǎo)入

沒有`__all__`

demo01.py:

# 全局變量

name = 'itcast'

def hello():

? ? print('hello')

class Person(object):

? ? def eat(self):

? ? ? ? print('eat')

demo02.py:

from demo01 import *

print(name)

hello()

per = Person()

per.eat()

運(yùn)行demo02.py ,? 可得結(jié)果:

itcast

hello

eat

模塊中有`__all__`

demo01.py:

__all__ = ['name', 'hello']

# 全局變量

name = 'itcast'

def hello():

? ? print('hello')

class Person(object):

? ? def eat(self):

? ? ? ? print('eat')

demo02.py:

from demo01 import *

print(name)

hello()

per = Person()

per.eat()

運(yùn)行demo02.py, 可得:

itcast

hello

Traceback (most recent call last):

? File "demo02.py", line 5, in <module>

? ? per = Person()

NameError: name 'Person' is not defined

上例中,如果我們把 Person 添加到`__all__`中,可得:

demo01.py:

__all__ = ['name', 'hello', 'Person']

# 全局變量

name = 'itcast'

def hello():

? ? print('hello')

class Person(object):

? ? def eat(self):

? ? ? ? print('eat')

demo02.py:

from demo01 import *

print(name)

hello()

per = Person()

per.eat()

運(yùn)行demo02.py, 可得:

itcast

hello

eat

總結(jié)

- 如果一個(gè)模塊中有`__all__`屬性抡秆,則只有`__all__`內(nèi)指定的屬性, 方法, 類可被導(dǎo)入, 當(dāng)然前提是使用from 模塊名 import * 的導(dǎo)入形式

- 這樣做有利于我們決定是否將模塊中的所有內(nèi)容都展示出去.? 可以有選擇性的進(jìn)行保留

- 在程序中一般定義接口的時(shí)候, 可能用到. 這里知道即可, 不做過多講解.

4. python中的包

>? 包是什么?? ? ? 其實(shí):? 包就是帶有`__init__.py`文件的文件夾

1). 引入包

> 在程序中, 我們往往會(huì)把有聯(lián)系的模塊放在一個(gè)包中? (即把有聯(lián)系的多個(gè).py文件放在一個(gè)特殊文件夾下)

> 特殊在哪里呢?? 這個(gè)文件夾下會(huì)有一個(gè)`__init__.py`的文件

我們?cè)趧?chuàng)建一個(gè)新的模塊(文件), 在新建的模塊中, 導(dǎo)入包里面的兩個(gè)文件:? ?

這兩個(gè)文件在包中, 所以我們導(dǎo)入的時(shí)候,也要把包名帶上:

2).包中的`__init__.py`文件

> `__init__.py` 控制著包的導(dǎo)入行為

總結(jié):

- 包將有聯(lián)系的模塊組織在一起,即放到同一個(gè)文件夾下吟策,并且在這個(gè)文件夾創(chuàng)建一個(gè)名字為`__init__.py` 文件儒士,那么這個(gè)文件夾就稱之為`包`

- 有效避免模塊名稱沖突問題,讓應(yīng)用組織結(jié)構(gòu)更加清晰

- `__init__.py`文件有什么用?

? - `__init__.py` 控制著包的導(dǎo)入行為

- `__init__.py`如果為空:

? * 僅僅是把這個(gè)包導(dǎo)入檩坚,不會(huì)導(dǎo)入包中的模塊

- `__all__`

? * 在`__init__.py`文件中着撩,定義一個(gè)`__all__`變量,它控制著 from 包名 import *時(shí)導(dǎo)入的模塊

- 也可以在`__init__`.py文件中定義一些方法,那么這些方法能在包導(dǎo)入后調(diào)用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匾委,一起剝皮案震驚了整個(gè)濱河市拖叙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赂乐,老刑警劉巖薯鳍,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異挨措,居然都是意外死亡挖滤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門浅役,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斩松,“玉大人,你說我怎么就攤上這事觉既【屙铮” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵瞪讼,是天一觀的道長(zhǎng)钧椰。 經(jīng)常有香客問我,道長(zhǎng)符欠,這世上最難降的妖魔是什么嫡霞? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮背亥,結(jié)果婚禮上秒际,老公的妹妹穿的比我還像新娘。我一直安慰自己狡汉,他們只是感情好娄徊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盾戴,像睡著了一般寄锐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天橄仆,我揣著相機(jī)與錄音剩膘,去河邊找鬼。 笑死盆顾,一個(gè)胖子當(dāng)著我的面吹牛怠褐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播您宪,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奈懒,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了宪巨?” 一聲冷哼從身側(cè)響起磷杏,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捏卓,沒想到半個(gè)月后极祸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怠晴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年遥金,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龄寞。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汰规,死狀恐怖汤功,靈堂內(nèi)的尸體忽然破棺而出物邑,到底是詐尸還是另有隱情,我是刑警寧澤滔金,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布色解,位于F島的核電站,受9級(jí)特大地震影響餐茵,放射性物質(zhì)發(fā)生泄漏科阎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一忿族、第九天 我趴在偏房一處隱蔽的房頂上張望锣笨。 院中可真熱鬧,春花似錦道批、人聲如沸错英。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椭岩。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間判哥,已是汗流浹背献雅。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留塌计,地道東北人挺身。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像锌仅,于是被迫代替她去往敵國和親瞒渠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354