日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

08-面向对象----

發(fā)布時間:2024/9/5 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 08-面向对象---- 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一 面向?qū)ο蟮某绦蛟O(shè)計的由來

請參考:http://www.cnblogs.com/linhaifeng/articles/6428835.html

二 什么是面向?qū)ο蟮某绦蛟O(shè)計及為什么要有它

面向過程的程序設(shè)計的核心是過程,過程即解決問題的步驟,面向過程的設(shè)計就好比精心設(shè)計好一條流水線,考慮周全什么時候處理什么東西。

優(yōu)點是:極大的降低了程序的復(fù)雜度

缺點是:一套流水線或者流程就是用來解決一個問題,生產(chǎn)汽水的流水線無法生產(chǎn)汽車,即便是能,也得是大改,改一個組件,牽一發(fā)而動全身。

應(yīng)用場景:一旦完成基本很少改變的場景,著名的例子有Linux內(nèi)核,git,以及Apache HTTP Server等。

面向?qū)ο蟮某绦蛟O(shè)計的核心是對象,要理解對象為何物,必須把自己當(dāng)成上帝,上帝眼里世間存在的萬物皆為對象,不存在的也可以創(chuàng)造出來。面向?qū)ο蟮某绦蛟O(shè)計好比如來設(shè)計西游記,如來要解決的問題是把經(jīng)書傳給東土大唐,如來想了想解決這個問題需要四個人:唐僧,沙和尚,豬八戒,孫悟空,每個人都有各自的特征和技能(這就是對象的概念,特征和技能分別對應(yīng)對象的數(shù)據(jù)屬性和方法屬性),然而這并不好玩,于是如來又安排了一群妖魔鬼怪,為了防止師徒四人在取經(jīng)路上被搞死,又安排了一群神仙保駕護(hù)航,這些都是對象。然后取經(jīng)開始,師徒四人與妖魔鬼怪神仙交互著直到最后取得真經(jīng)。如來根本不會管師徒四人按照什么流程去取。

面向?qū)ο蟮某绦蛟O(shè)計的

優(yōu)點是:解決了程序的擴(kuò)展性。對某一個對象單獨修改,會立刻反映到整個體系中,如對游戲中一個人物參數(shù)的特征和技能修改都很容易。

缺點:可控性差,無法向面向過程的程序設(shè)計流水線式的可以很精準(zhǔn)的預(yù)測問題的處理流程與結(jié)果,面向?qū)ο蟮某绦蛞坏╅_始就由對象之間的交互解決問題,即便是上帝也無法預(yù)測最終結(jié)果。于是我們經(jīng)常看到一個游戲人某一參數(shù)的修改極有可能導(dǎo)致陰霸的技能出現(xiàn),一刀砍死3個人,這個游戲就失去平衡。

應(yīng)用場景:需求經(jīng)常變化的軟件,一般需求的變化都集中在用戶層,互聯(lián)網(wǎng)應(yīng)用,企業(yè)內(nèi)部軟件,游戲等都是面向?qū)ο蟮某绦蛟O(shè)計大顯身手的好地方

面向?qū)ο蟮某绦蛟O(shè)計并不是全部。對于一個軟件質(zhì)量來說,面向?qū)ο蟮某绦蛟O(shè)計只是用來解決擴(kuò)展性。

三 類和對象

提示:python的class術(shù)語與c++有一定區(qū)別,與 Modula-3更像。

python中一切皆為對象,且python3統(tǒng)一了類與類型的概念,類型就是類,所以,不管你信不信,你已經(jīng)使用了很長時間的類了

1 >>> dict #類型dict就是類dict 2 <class 'dict'> 3 >>> d=dict(name='egon') #實例化 4 >>> d.pop('name') #向d發(fā)一條消息,執(zhí)行d的方法pop 5 'egon'

基于面向?qū)ο笤O(shè)計一個款游戲:英雄聯(lián)盟,每個玩家選一個英雄,每個英雄都有自己的特征和和技能,特征即數(shù)據(jù)屬性,技能即方法屬性,特征與技能的結(jié)合體就一個對象。

從一組對象中提取相似的部分就是,類也是特征與技能的結(jié)合體,特征即數(shù)據(jù)并且是所有對象共享的數(shù)據(jù),技能即函數(shù)屬性并且是所有對象共享的函數(shù)屬性。

garen_hero.Q()稱為向garen_hero這個對象發(fā)送了一條消息,讓他去執(zhí)行Q這個函數(shù),完成一個功能,類似的有:

garen_hero.W()

garen_hero.E()

garen_hero.R()

一個英雄可以攻擊另外一個英雄,這就是對象之間的交互

garen_hero.attack(Riven)

?

?

3.1 類相關(guān)知識

3.1.1 初識類

在python中聲明函數(shù)與聲明類很相似

聲明函數(shù)

1 def functionName(args): 2 '函數(shù)文檔字符串' 3 函數(shù)體 1 ''' 2 class 類名: 3 '類的文檔字符串' 4 類體 5 ''' 6 7 #我們創(chuàng)建一個類 8 class Data: 9 pass 1 大前提: 2 1.只有在python2中才分新式類和經(jīng)典類,python3中統(tǒng)一都是新式類 3 2.新式類和經(jīng)典類聲明的最大不同在于,所有新式類必須繼承至少一個父類 4 3.所有類甭管是否顯式聲明父類,都有一個默認(rèn)繼承object父類(講繼承時會講,先記住) 5 在python2中的區(qū)分 6 經(jīng)典類: 7 class 類名: 8 pass 9 10 經(jīng)典類: 11 class 類名(父類): 12 pass 13 14 在python3中,上述兩種定義方式全都是新式類 在本節(jié)開頭介紹得出結(jié)論,類是數(shù)據(jù)與函數(shù)的結(jié)合,二者稱為類的屬性 class Garen: #定義英雄蓋倫的類,不同的玩家可以用它實例出自己英雄;camp='Demacia' #所有玩家的英雄(蓋倫)的陣營都是Demacia;def attack(self,enemy): #普通攻擊技能,enemy是敵人;enemy.life_value-=self.aggressivity #根據(jù)自己的攻擊力,攻擊敵人就減掉敵人的生命值。

3.1.2 類有兩種作用:屬性引用和實例化

3.1.2.1 屬性引用(類名.屬性)

>>> Garen.camp #引用類的數(shù)據(jù)屬性,該屬性與所有對象/實例共享 'Demacia' >>> Garen.attack #引用類的函數(shù)屬性,該屬性也共享 <function Garen.attack at 0x101356510> >>> Garen.name='Garen' #增加屬性 >>> del Garen.name #刪除屬性

3.1.2.2 實例化(__init__與self)

類名加括號就是實例化,會自動觸發(fā)__init__函數(shù)的運行,可以用它來為每個實例定制自己的特征

class Garen: #定義英雄蓋倫的類,不同的玩家可以用它實例出自己英雄;camp='Demacia' #所有玩家的英雄(蓋倫)的陣營都是Demacia;def __init__(self,nickname,aggressivity=58,life_value=455): #英雄的初始攻擊力58...;self.nickname=nickname #為自己的蓋倫起個別名;self.aggressivity=aggressivity #英雄都有自己的攻擊力;self.life_value=life_value #英雄都有自己的生命值;def attack(self,enemy): #普通攻擊技能,enemy是敵人;enemy.life_value-=self.aggressivity #根據(jù)自己的攻擊力,攻擊敵人就減掉敵人的生命值。

實例化:類名+括號

>>> g1=Garen('草叢倫') #就是在執(zhí)行Garen.__init__(g1,'草叢倫'),然后執(zhí)行__init__內(nèi)的代碼g1.nickname=‘草叢倫’等

self的作用是在實例化時自動將對象/實例本身傳給__init__的第一個參數(shù),self可以是任意名字,但是瞎幾把寫別人就看不懂了。

這種自動傳遞的機(jī)制還體現(xiàn)在g1.attack的調(diào)用上,后續(xù)會介紹。

一:我們定義的類的屬性到底存到哪里了?有兩種方式查看 dir(類名):查出的是一個名字列表 類名.__dict__:查出的是一個字典,key為屬性名,value為屬性值二:特殊的類屬性 類名.__name__# 類的名字(字符串) 類名.__doc__# 類的文檔字符串 類名.__base__# 類的第一個父類(在講繼承時會講) 類名.__bases__# 類所有父類構(gòu)成的元組(在講繼承時會講) 類名.__dict__# 類的字典屬性 類名.__module__# 類定義所在的模塊 類名.__class__# 實例對應(yīng)的類(僅新式類中)

3.2 對象相關(guān)知識

對象是關(guān)于類而實際存在的一個例子,即實例

>>> g1=Garen('草叢倫') #類實例化得到g1這個實例,基于該實例我們講解實例相關(guān)知識

3.2.1 對象/實例只有一種作用:屬性引用

#對象/實例本身其實只有數(shù)據(jù)屬性 >>> g1.nickname '草叢倫' >>> g1.aggressivity 58 >>> g1.life_value 455 ''' 查看實例屬性 同樣是dir和內(nèi)置__dict__兩種方式 特殊實例屬性 __class__ __dict__ .... '''

對象/實例本身只有數(shù)據(jù)屬性,但是python的class機(jī)制會將類的函數(shù)綁定到對象上,稱為對象的方法,或者叫綁定方法

>>> g1.attack #對象的綁定方法 <bound method Garen.attack of <__main__.Garen object at 0x101348dd8>>>>> Garen.attack #對象的綁定方法attack本質(zhì)就是調(diào)用類的函數(shù)attack的功能,二者是一種綁定關(guān)系 <function Garen.attack at 0x101356620>

對象的綁定方法的特別之處在于:obj.func()會把obj傳給func的第一個參數(shù)。

3.3 對象之間的交互

我們可以仿照garen類再創(chuàng)建一個Riven類

class Riven:camp='Noxus' #所有玩家的英雄(銳雯)的陣營都是Noxus;def __init__(self,nickname,aggressivity=54,life_value=414): #英雄的初始攻擊力54;self.nickname=nickname #為自己的銳雯起個別名;self.aggressivity=aggressivity #英雄都有自己的攻擊力;self.life_value=life_value #英雄都有自己的生命值;def attack(self,enemy): #普通攻擊技能,enemy是敵人;enemy.life_value-=self.aggressivity #根據(jù)自己的攻擊力,攻擊敵人就減掉敵人的生命值。

實例出一個Riven來

>>> r1=Riven('銳雯雯')

交互:銳雯雯攻擊草叢倫,反之一樣

>>> g1.life_value 455 >>> r1.attack(g1) >>> g1.life_value 401

3.4 類名稱空間與對象/實例名稱空間

創(chuàng)建一個類就會創(chuàng)建一個類的名稱空間,用來存儲類中定義的所有名字,這些名字稱為類的屬性

而類有兩種屬性:數(shù)據(jù)屬性和函數(shù)屬性

其中類的數(shù)據(jù)屬性是共享給所有對象的

>>> id(r1.camp) #本質(zhì)就是在引用類的camp屬性,二者id一樣 4315241024 >>> id(Riven.camp) 4315241024

而類的函數(shù)屬性是綁定到所有對象的:

>>> id(r1.attack) 4302501512 >>> id(Riven.attack) 4315244200''' r1.attack就是在執(zhí)行Riven.attack的功能,python的class機(jī)制會將Riven的函數(shù)屬性attack綁定給r1,r1相當(dāng)于拿到了一個指針,指向Riven類的attack功能除此之外r1.attack()會將r1傳給attack的第一個參數(shù) '''

創(chuàng)建一個對象/實例就會創(chuàng)建一個對象/實例的名稱空間,存放對象/實例的名字,稱為對象/實例的屬性

在obj.name會先從obj自己的名稱空間里找name,找不到則去類中找,類也找不到就找父類...最后都找不到就拋出異常?

3.5 小結(jié)

瑞文

class Riven:camp='Noxus'def __init__(self,nickname,aggressivity=54,life_value=414,money=1001,armor=3):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valueself.money=moneyself.armor=armordef attack(self,enemy):damage_value=self.aggressivity-enemy.armorenemy.life_value-=damage_value

蓋倫

class Garen:camp='Demacia'def __init__(self,nickname,aggressivity=58,life_value=455,money=100,armor=10):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valueself.money=moneyself.armor=armordef attack(self,enemy):damage_value=self.aggressivity-enemy.armorenemy.life_value-=damage_value

定義裝備:

class BlackCleaver:def __init__(self,price=475,aggrev=9,life_value=100):self.price=priceself.aggrev=aggrevself.life_value=life_valuedef update(self,obj):obj.money-=self.price #減錢obj.aggressivity+=self.aggrev #加攻擊obj.life_value+=self.life_value #加生命值def fire(self,obj): #這是該裝備的主動技能,噴火,燒死對方obj.life_value-=1000 #假設(shè)火燒的攻擊力是1000

測試交互

r1=Riven('草叢倫') g1=Garen('蓋文') b1=BlackCleaver()print(r1.aggressivity,r1.life_value,r1.money) #r1的攻擊力,生命值,護(hù)甲if r1.money > b1.price:r1.b1=b1b1.update(r1)print(r1.aggressivity,r1.life_value,r1.money) #r1的攻擊力,生命值,護(hù)甲print(g1.life_value) r1.attack(g1) #普通攻擊 print(g1.life_value) r1.b1.fire(g1) #用裝備攻擊 print(g1.life_value) #g1的生命值小于0就死了

按照這種思路一點一點的設(shè)計類和對象,最終你完全可以實現(xiàn)一個對戰(zhàn)類游戲。

四 繼承與派生

4.1 什么是繼承

繼承是一種創(chuàng)建新的類的方式,在python中,新建的類可以繼承自一個或者多個父類,原始類稱為基類或超類,新建的類稱為派生類或子類。

python中類的繼承分為:單繼承和多繼承

class ParentClass1: #定義父類passclass ParentClass2: #定義父類passclass SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClasspassclass SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類pass

查看繼承

>>> SubClass1.__bases__ (<class '__main__.ParentClass1'>,) >>> SubClass2.__bases__ (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

提示:如果沒有指定基類,python的類會默認(rèn)繼承object類,object是所有python類的基類,它提供了一些常見方法(如__str__)的實現(xiàn)。

>>> ParentClass1.__bases__ (<class 'object'>,) >>> ParentClass2.__bases__ (<class 'object'>,)

4.2 繼承與抽象(先抽象再繼承)

抽象即抽取類似或者說比較像的部分。

抽象分成兩個層次:?

1.將奧巴馬和梅西這倆對象比較像的部分抽取成類;?

2.將人,豬,狗這三個類比較像的部分抽取成父類。

抽象最主要的作用是劃分類別(可以隔離關(guān)注點,降低復(fù)雜度)

繼承:是基于抽象的結(jié)果,通過編程語言去實現(xiàn)它,肯定是先經(jīng)歷抽象這個過程,才能通過繼承的方式去表達(dá)出抽象的結(jié)構(gòu)。

抽象只是分析和設(shè)計的過程中,一個動作或者說一種技巧,通過抽象可以得到類

4.3 繼承與重用性

==========================第一部分 例如貓可以:喵喵叫、吃、喝、拉、撒狗可以:汪汪叫、吃、喝、拉、撒如果我們要分別為貓和狗創(chuàng)建一個類,那么就需要為 貓 和 狗 實現(xiàn)他們所有的功能,偽代碼如下:#貓和狗有大量相同的內(nèi)容 class 貓:def 喵喵叫(self):print '喵喵叫'def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do somethingclass 狗:def 汪汪叫(self):print '喵喵叫'def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do something==========================第二部分 上述代碼不難看出,吃、喝、拉、撒是貓和狗都具有的功能,而我們卻分別的貓和狗的類中編寫了兩次。如果使用 繼承 的思想,如下實現(xiàn):動物:吃、喝、拉、撒貓:喵喵叫(貓繼承動物的功能)狗:汪汪叫(狗繼承動物的功能)偽代碼如下: class 動物:def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do something# 在類后面括號中寫入另外一個類名,表示當(dāng)前類繼承另外一個類 class 貓(動物):def 喵喵叫(self):print '喵喵叫'# 在類后面括號中寫入另外一個類名,表示當(dāng)前類繼承另外一個類 class 狗(動物):def 汪汪叫(self):print '喵喵叫'==========================第三部分 #繼承的代碼實現(xiàn) class Animal:def eat(self):print("%s 吃 " %self.name)def drink(self):print ("%s 喝 " %self.name)def shit(self):print ("%s 拉 " %self.name)def pee(self):print ("%s 撒 " %self.name)class Cat(Animal):def __init__(self, name):self.name = nameself.breed = '貓'def cry(self):print('喵喵叫')class Dog(Animal):def __init__(self, name):self.name = nameself.breed='狗'def cry(self):print('汪汪叫')# ######### 執(zhí)行 #########c1 = Cat('小白家的小黑貓') c1.eat()c2 = Cat('小黑的小白貓') c2.drink()d1 = Dog('胖子家的小瘦狗') d1.eat() view code

在開發(fā)程序的過程中,如果我們定義了一個類A,然后又想新建立另外一個類B,但是類B的大部分內(nèi)容與類A的相同時

我們不可能從頭開始寫一個類B,這就用到了類的繼承的概念。

通過繼承的方式新建類B,讓B繼承A,B會‘遺傳’A的所有屬性(數(shù)據(jù)屬性和函數(shù)屬性),實現(xiàn)代碼重用

class Hero:def __init__(self,nickname,aggressivity,life_value):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valuedef move_forward(self):print('%s move forward' %self.nickname)def move_backward(self):print('%s move backward' %self.nickname)def move_left(self):print('%s move forward' %self.nickname)def move_right(self):print('%s move forward' %self.nickname)def attack(self,enemy):enemy.life_value-=self.aggressivity class Garen(Hero):passclass Riven(Hero):passg1=Garen('草叢倫',100,300) r1=Riven('銳雯雯',57,200)print(g1.life_value) r1.attack(g1) print(g1.life_value)''' 運行結(jié)果 300 243 ''' view code

提示:用已經(jīng)有的類建立一個新的類,這樣就重用了已經(jīng)有的軟件中的一部分設(shè)置大部分,大大生了編程工作量,這就是常說的軟件重用,不僅可以重用自己的類,也可以繼承別人的,比如標(biāo)準(zhǔn)庫,來定制新的數(shù)據(jù)類型,這樣就是大大縮短了軟件開發(fā)周期,對大型軟件開發(fā)來說,意義重大.

注意:像g1.life_value之類的屬性引用,會先從實例中找life_value然后去類中找,然后再去父類中找...直到最頂級的父類。

當(dāng)然子類也可以添加自己新的屬性或者在自己這里重新定義這些屬性(不會影響到父類),需要注意的是,一旦重新定義了自己的屬性且與父類重名,那么調(diào)用新增的屬性時,就以自己為準(zhǔn)了。

class Riven(Hero):camp='Noxus'def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname) view code

在子類中,新建的重名的函數(shù)屬性,在編輯函數(shù)內(nèi)功能的時候,有可能需要重用父類中重名的那個函數(shù)功能,應(yīng)該是用調(diào)用普通函數(shù)的方式,即:類名.func(),此時就與調(diào)用普通函數(shù)無異了,因此即便是self參數(shù)也要為其傳值

class Riven(Hero):camp='Noxus'def __init__(self,nickname,aggressivity,life_value,skin):Hero.__init__(self,nickname,aggressivity,life_value) #調(diào)用父類功能self.skin=skin #新屬性def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類Hero.attack(self,enemy) #調(diào)用功能print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname)r1=Riven('銳雯雯',57,200,'比基尼') r1.fly() print(r1.skin)''' 運行結(jié)果 銳雯雯 is flying 比基尼''' view code

4.4 組合與重用性

軟件重用的重要方式除了繼承之外還有另外一種方式,即:組合

組合指的是,在一個類中以另外一個類的對象作為數(shù)據(jù)屬性,稱為類的組合

其實早在3.5小節(jié)中我們就體會了組合的用法,比如一個英雄有一個裝備

>>> class Equip: #武器裝備類 ... def fire(self): ... print('release Fire skill') ... >>> class Riven: #英雄Riven的類,一個英雄需要有裝備,因而需要組合Equip類 ... camp='Noxus' ... def __init__(self,nickname): ... self.nickname=nickname ... self.equip=Equip() #用Equip類產(chǎn)生一個裝備,賦值給實例的equip屬性 ... >>> r1=Riven('銳雯雯') >>> r1.equip.fire() #可以使用組合的類產(chǎn)生的對象所持有的方法 release Fire skill view code

組合與繼承都是有效地利用已有類的資源的重要方式。但是二者的概念和使用場景皆不同,

1.繼承的方式

通過繼承建立了派生類與基類之間的關(guān)系,它是一種'是'的關(guān)系,比如白馬是馬,人是動物。

當(dāng)類之間有很多相同的功能,提取這些共同的功能做成基類,用繼承比較好,比如教授是老師

>>> class Teacher: ... def __init__(self,name,gender): ... self.name=name ... self.gender=gender ... def teach(self): ... print('teaching') ... >>> >>> class Professor(Teacher): ... pass ... >>> p1=Professor('egon','male') >>> p1.teach() teaching view code

2.組合的方式

用組合的方式建立了類與組合的類之間的關(guān)系,它是一種‘有’的關(guān)系,比如教授有生日,教授教python課程

class BirthDate:def __init__(self,year,month,day):self.year=yearself.month=monthself.day=dayclass Couse:def __init__(self,name,price,period):self.name=nameself.price=priceself.period=periodclass Teacher:def __init__(self,name,gender):self.name=nameself.gender=genderdef teach(self):print('teaching') class Professor(Teacher):def __init__(self,name,gender,birth,course):Teacher.__init__(self,name,gender)self.birth=birthself.course=coursep1=Professor('egon','male',BirthDate('1995','1','27'),Couse('python','28000','4 months'))print(p1.birth.year,p1.birth.month,p1.birth.day) print(p1.course.name,p1.course.price,p1.course.period) ''' 運行結(jié)果: 1995 1 27 python 28000 4 months ''' view code

當(dāng)類之間有顯著不同,并且較小的類是較大的類所需要的組件時,用組合比較好

4.5 接口與歸一化設(shè)計

1.什么是接口

=================第一部分:Java 語言中的接口很好的展現(xiàn)了接口的含義: IAnimal.java /* * Java的Interface很好的體現(xiàn)了我們前面分析的接口的特征: * 1)是一組功能的集合,而不是一個功能 * 2)接口的功能用于交互,所有的功能都是public,即別的對象可操作 * 3)接口只定義函數(shù),但不涉及函數(shù)實現(xiàn) * 4)這些功能是相關(guān)的,都是動物相關(guān)的功能,但光合作用就不適宜放到IAnimal里面了 */package com.oo.demo; public interface IAnimal {public void eat();public void run();public void sleep();public void speak(); }=================第二部分:Pig.java:豬”的類設(shè)計,實現(xiàn)了IAnnimal接口 package com.oo.demo; public class Pig implements IAnimal{ //如下每個函數(shù)都需要詳細(xì)實現(xiàn)public void eat(){System.out.println("Pig like to eat grass");}public void run(){System.out.println("Pig run: front legs, back legs");}public void sleep(){System.out.println("Pig sleep 16 hours every day");}public void speak(){System.out.println("Pig can not speak"); } }=================第三部分:Person2.java /* *實現(xiàn)了IAnimal的“人”,有幾點說明一下: * 1)同樣都實現(xiàn)了IAnimal的接口,但“人”和“豬”的實現(xiàn)不一樣,為了避免太多代碼導(dǎo)致影響閱讀,這里的代碼簡化成一行,但輸出的內(nèi)容不一樣,實際項目中同一接口的同一功能點,不同的類實現(xiàn)完全不一樣 * 2)這里同樣是“人”這個類,但和前面介紹類時給的類“Person”完全不一樣,這是因為同樣的邏輯概念,在不同的應(yīng)用場景下,具備的屬性和功能是完全不一樣的 */package com.oo.demo; public class Person2 implements IAnimal {public void eat(){System.out.println("Person like to eat meat");}public void run(){System.out.println("Person run: left leg, right leg");}public void sleep(){System.out.println("Person sleep 8 hours every dat");}public void speak(){System.out.println("Hellow world, I am a person");} }=================第四部分:Tester03.java package com.oo.demo;public class Tester03 {public static void main(String[] args) {System.out.println("===This is a person===");IAnimal person = new Person2();person.eat();person.run();person.sleep();person.speak();System.out.println("\n===This is a pig===");IAnimal pig = new Pig();pig.eat();pig.run();pig.sleep();pig.speak();} } view code

繼承有兩種用途:

一:繼承基類的方法,并且做出自己的改變或者擴(kuò)展(代碼重用)

二:聲明某個子類兼容于某基類,定義一個接口類Interface,接口類中定義了一些接口名(就是函數(shù)名)且并未實現(xiàn)接口的功能,子類繼承接口類,并且實現(xiàn)接口中的功能

class Interface:#定義接口Interface類來模仿接口的概念,python中壓根就沒有interface關(guān)鍵字來定義一個接口。def read(self): #定接口函數(shù)readpassdef write(self): #定義接口函數(shù)writepassclass Txt(Interface): #文本,具體實現(xiàn)read和writedef read(self):print('文本數(shù)據(jù)的讀取方法')def write(self):print('文本數(shù)據(jù)的讀取方法')class Sata(Interface): #磁盤,具體實現(xiàn)read和writedef read(self):print('硬盤數(shù)據(jù)的讀取方法')def write(self):print('硬盤數(shù)據(jù)的讀取方法')class Process(All_file):def read(self):print('進(jìn)程數(shù)據(jù)的讀取方法')def write(self):print('進(jìn)程數(shù)據(jù)的讀取方法') view code

實踐中,繼承的第一種含義意義并不很大,甚至常常是有害的。因為它使得子類與基類出現(xiàn)強(qiáng)耦合。

繼承的第二種含義非常重要。它又叫“接口繼承”。
接口繼承實質(zhì)上是要求“做出一個良好的抽象,這個抽象規(guī)定了一個兼容接口,使得外部調(diào)用者無需關(guān)心具體細(xì)節(jié),可一視同仁的處理實現(xiàn)了特定接口的所有對象”——這在程序設(shè)計上,叫做歸一化。

歸一化使得高層的外部使用者可以不加區(qū)分的處理所有接口兼容的對象集合——就好象linux的泛文件概念一樣,所有東西都可以當(dāng)文件處理,不必關(guān)心它是內(nèi)存、磁盤、網(wǎng)絡(luò)還是屏幕(當(dāng)然,對底層設(shè)計者,當(dāng)然也可以區(qū)分出“字符設(shè)備”和“塊設(shè)備”,然后做出針對性的設(shè)計:細(xì)致到什么程度,視需求而定)。

在python中根本就沒有一個叫做interface的關(guān)鍵字,上面的代碼只是看起來像接口,其實并沒有起到接口的作用,子類完全可以不用去實現(xiàn)接口 ,如果非要去模仿接口的概念,可以借助第三方模塊:

http://pypi.python.org/pypi/zope.interface

twisted的twisted\internet\interface.py里使用zope.interface

文檔https://zopeinterface.readthedocs.io/en/latest/

2. 為何要用接口

接口提取了一群類共同的函數(shù),可以把接口當(dāng)做一個函數(shù)的集合。

然后讓子類去實現(xiàn)接口中的函數(shù)。

這么做的意義在于歸一化,什么叫歸一化,就是只要是基于同一個接口實現(xiàn)的類,那么所有的這些類產(chǎn)生的對象在使用時,從用法上來說都一樣。

歸一化,讓使用者無需關(guān)心對象的類是什么,只需要的知道這些對象都具備某些功能就可以了,這極大地降低了使用者的使用難度。

比如:我們定義一個動物接口,接口里定義了有跑、吃、呼吸等接口函數(shù),這樣老鼠的類去實現(xiàn)了該接口,松鼠的類也去實現(xiàn)了該接口,由二者分別產(chǎn)生一只老鼠和一只松鼠送到你面前,即便是你分別不到底哪只是什么鼠你肯定知道他倆都會跑,都會吃,都能呼吸。

再比如:我們有一個汽車接口,里面定義了汽車所有的功能,然后由本田汽車的類,奧迪汽車的類,大眾汽車的類,他們都實現(xiàn)了汽車接口,這樣就好辦了,大家只需要學(xué)會了怎么開汽車,那么無論是本田,還是奧迪,還是大眾我們都會開了,開的時候根本無需關(guān)心我開的是哪一類車,操作手法(函數(shù)調(diào)用)都一樣

4.6 抽象類

1 什么是抽象類

??? 與java一樣,python也有抽象類的概念但是同樣需要借助模塊實現(xiàn),抽象類是一個特殊的類,它的特殊之處在于只能被繼承,不能被實例化

2 為什么要有抽象類

??? 如果說類是從一堆對象中抽取相同的內(nèi)容而來的,那么抽象類是從一堆中抽取相同的內(nèi)容而來的,內(nèi)容包括數(shù)據(jù)屬性和函數(shù)屬性。

  比如我們有香蕉的類,有蘋果的類,有桃子的類,從這些類抽取相同的內(nèi)容就是水果這個抽象的類,你吃水果時,要么是吃一個具體的香蕉,要么是吃一個具體的桃子。。。。。。你永遠(yuǎn)無法吃到一個叫做水果的東西。

??? 從設(shè)計角度去看,如果類是從現(xiàn)實對象抽象而來的,那么抽象類就是基于類抽象而來的。

  從實現(xiàn)角度來看,抽象類與普通類的不同之處在于:抽象類中只能有抽象方法(沒有實現(xiàn)功能),該類不能被實例化,只能被繼承,且子類必須實現(xiàn)抽象方法。這一點與接口有點類似,但其實是不同的,即將揭曉答案

3. 在python中實現(xiàn)抽象類

#_*_coding:utf-8_*_ #一切皆文件 import abc #利用abc模塊實現(xiàn)抽象類class All_file(metaclass=abc.ABCMeta):all_type='file'@abc.abstractmethod #定義抽象方法,無需實現(xiàn)功能def read(self):'子類必須定義讀功能'pass@abc.abstractmethod #定義抽象方法,無需實現(xiàn)功能def write(self):'子類必須定義寫功能'pass# class Txt(All_file): # pass # # t1=Txt() #報錯,子類沒有定義抽象方法class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('文本數(shù)據(jù)的讀取方法')def write(self):print('文本數(shù)據(jù)的讀取方法')class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('硬盤數(shù)據(jù)的讀取方法')def write(self):print('硬盤數(shù)據(jù)的讀取方法')class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('進(jìn)程數(shù)據(jù)的讀取方法')def write(self):print('進(jìn)程數(shù)據(jù)的讀取方法')wenbenwenjian=Txt()yingpanwenjian=Sata()jinchengwenjian=Process()#這樣大家都是被歸一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read()print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type) view code

4. 抽象類與接口

抽象類的本質(zhì)還是類,指的是一組類的相似性,包括數(shù)據(jù)屬性(如all_type)和函數(shù)屬性(如read、write),而接口只強(qiáng)調(diào)函數(shù)屬性的相似性。

抽象類是一個介于類和接口直接的一個概念,同時具備類和接口的部分特性,可以用來實現(xiàn)歸一化設(shè)計

4.7 繼承實現(xiàn)的原理(繼承順序)

1 繼承順序

class A(object):def test(self):print('from A')class B(A):def test(self):print('from B')class C(A):def test(self):print('from C')class D(B):def test(self):print('from D')class E(C):def test(self):print('from E')class F(D,E):# def test(self):# print('from F')pass f1=F() f1.test() print(F.__mro__) #只有新式才有這個屬性可以查看線性列表,經(jīng)典類沒有這個屬性#新式類繼承順序:F->D->B->E->C->A #經(jīng)典類繼承順序:F->D->B->A->E->C #python3中統(tǒng)一都是新式類 #pyhon2中才分新式類與經(jīng)典類 view code

2 繼承原理(python如何實現(xiàn)的繼承)

python到底是如何實現(xiàn)繼承的,對于你定義的每一個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的所有基類的線性順序列表,例如

>>> F.mro() #等同于F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] view code

為了實現(xiàn)繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。
而這個MRO列表的構(gòu)造是通過一個C3線性化算法來實現(xiàn)的。我們不去深究這個算法的數(shù)學(xué)原理,它實際上就是合并所有父類的MRO列表并遵循如下三條準(zhǔn)則:
1.子類會先于父類被檢查
2.多個父類會根據(jù)它們在列表中的順序被檢查
3.如果對下一個類存在兩個合法的選擇,選擇第一個父類

4.8 子類中調(diào)用父類方法

子類繼承了父類的方法,然后想進(jìn)行修改,注意了是基于原有的基礎(chǔ)上修改,那么就需要在子類中調(diào)用父類的方法

方法一:父類名.父類方法()

#_*_coding:utf-8_*_ class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):Vehicle.__init__(self,name,speed,load,power)self.line=linedef run(self):print('地鐵%s號線歡迎您' %self.line)Vehicle.run(self)line13=Subway('中國地鐵','180m/s','1000人/箱','電',13) line13.run() view code

方法二:super()

class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):#super(Subway,self) 就相當(dāng)于實例本身 在python3中super()等同于super(Subway,self)super().__init__(name,speed,load,power)self.line=linedef run(self):print('地鐵%s號線歡迎您' %self.line)super(Subway,self).run()class Mobike(Vehicle):#摩拜單車passline13=Subway('中國地鐵','180m/s','1000人/箱','電',13) line13.run() view code

不用super引發(fā)的慘案

#每個類中都繼承了且重寫了父類的方法 class A:def __init__(self):print('A的構(gòu)造方法') class B(A):def __init__(self):print('B的構(gòu)造方法')A.__init__(self)class C(A):def __init__(self):print('C的構(gòu)造方法')A.__init__(self)class D(B,C):def __init__(self):print('D的構(gòu)造方法')B.__init__(self)C.__init__(self)pass f1=D()print(D.__mro__) #python2中沒有這個屬性 view code

當(dāng)你使用super()函數(shù)時,Python會在MRO列表上繼續(xù)搜索下一個類。只要每個重定義的方法統(tǒng)一使用super()并只調(diào)用它一次,那么控制流最終會遍歷完整個MRO列表,每個方法也只會被調(diào)用一次

注意注意注意:使用super調(diào)用的所有屬性,都是從MRO列表當(dāng)前的位置往后找,千萬不要通過看代碼去找繼承關(guān)系,一定要看MRO列表

#每個類中都繼承了且重寫了父類的方法 class A:def __init__(self):print('A的構(gòu)造方法') class B(A):def __init__(self):print('B的構(gòu)造方法')super(B,self).__init__()class C(A):def __init__(self):print('C的構(gòu)造方法')super(C,self).__init__()class D(B,C):def __init__(self):print('D的構(gòu)造方法')super(D,self).__init__()f1=D()print(D.__mro__) #python2中沒有這個屬性 view code

五 多態(tài)與多態(tài)性

5.1 多態(tài)

多態(tài)指的是一類事物有多種形態(tài),(一個抽象類有多個子類,因而多態(tài)的概念依賴于繼承)

1. 序列類型有多種形態(tài):字符串,列表,元組。

2. 動物有多種形態(tài):人,狗,豬

import abc class Animal(metaclass=abc.ABCMeta): #同一類事物:動物@abc.abstractmethoddef talk(self):passclass People(Animal): #動物的形態(tài)之一:人def talk(self):print('say hello')class Dog(Animal): #動物的形態(tài)之二:狗def talk(self):print('say wangwang')class Pig(Animal): #動物的形態(tài)之三:豬def talk(self):print('say aoao') view code

3. 文件有多種形態(tài):文件文件,可執(zhí)行文件

import abc class File(metaclass=abc.ABCMeta): #同一類事物:文件@abc.abstractmethoddef click(self):passclass Text(File): #文件的形態(tài)之一:文本文件def click(self):print('open file')class ExeFile(File): #文件的形態(tài)之二:可執(zhí)行文件def click(self):print('execute file') view code

5.2 多態(tài)性

一 什么是多態(tài)性(請務(wù)必注意注意注意:多態(tài)與多態(tài)性是兩種概念。)

多態(tài)性是指具有不同功能的函數(shù)可以使用相同的函數(shù)名,這樣就可以用一個函數(shù)名調(diào)用不同內(nèi)容的函數(shù)。

在面向?qū)ο蠓椒ㄖ幸话闶沁@樣表述多態(tài)性:向不同的對象發(fā)送同一條消息,不同的對象在接收時會產(chǎn)生不同的行為(即方法)。也就是說,每個對象可以用自己的方式去響應(yīng)共同的消息。所謂消息,就是調(diào)用函數(shù),不同的行為就是指不同的實現(xiàn),即執(zhí)行不同的函數(shù)。

多態(tài)性分為靜態(tài)多態(tài)性和動態(tài)多態(tài)性

靜態(tài)多態(tài)性:如任何類型都可以用運算符+進(jìn)行運算

動態(tài)多態(tài)性:如下

1.?

2.

>>> def func(animal): #參數(shù)animal就是對態(tài)性的體現(xiàn) ... animal.talk() ... >>> people1=People() #產(chǎn)生一個人的對象 >>> pig1=Pig() #產(chǎn)生一個豬的對象 >>> dog1=Dog() #產(chǎn)生一個狗的對象 >>> func(people1) say hello >>> func(pig1) say aoao >>> func(dog1) say wangwang view code

3.?

>>> def func(f): ... f.click() ... >>> t1=Text() >>> e1=ExeFile() >>> func(t1) open file >>> func(e1) execute file view code

綜上我們也可以說,多態(tài)性是‘一個接口(函數(shù)func),多種實現(xiàn)(如f.click())’

二 為什么要用多態(tài)性(多態(tài)性的好處)

其實大家從上面多態(tài)性的例子可以看出,我們并沒有增加什么新的知識,也就是說python本身就是支持多態(tài)性的,這么做的好處是什么呢?

1.增加了程序的靈活性

  以不變應(yīng)萬變,不論對象千變?nèi)f化,使用者都是同一種形式去調(diào)用,如func(animal)

2.增加了程序額可擴(kuò)展性

通過繼承animal類創(chuàng)建了一個新的類,使用者無需更改自己的代碼,還是用func(animal)去調(diào)用?

>>> class Cat(Animal): #屬于動物的另外一種形態(tài):貓 ... def talk(self): ... print('say miao') ... >>> def func(animal): #對于使用者來說,自己的代碼根本無需改動 ... animal.talk() ... >>> cat1=Cat() #實例出一只貓 >>> func(cat1) #甚至連調(diào)用方式也無需改變,就能調(diào)用貓的talk功能 say miao''' 這樣我們新增了一個形態(tài)Cat,由Cat類產(chǎn)生的實例cat1,使用者可以在完全不需要修改自己代碼的情況下。使用和人、狗、豬一樣的方式調(diào)用cat1的talk方法,即func(cat1) ''' view code

六 封裝

從封裝本身的意思去理解,封裝就好像是拿來一個麻袋,把小貓,小狗,小王八,還有alex一起裝進(jìn)麻袋,然后把麻袋封上口子。但其實這種理解相當(dāng)片面

??? 首先我們要了解

6.1 要封裝什么

你錢包的有多少錢(數(shù)據(jù)的封裝)

你的性取向(數(shù)據(jù)的封裝)

你撒尿的具體功能是怎么實現(xiàn)的(方法的封裝)

6.2 為什么要封裝

封裝數(shù)據(jù)的主要原因是:保護(hù)隱私(作為男人的你,臉上就寫著:我喜歡男人,你害怕么?)

封裝方法的主要原因是:隔離復(fù)雜度(快門就是傻瓜相機(jī)為傻瓜們提供的方法,該方法將內(nèi)部復(fù)雜的照相功能都隱藏起來了,比如你不必知道你自己的尿是怎么流出來的,你直接掏出自己的接口就能用尿這個功能)

你的身體沒有一處不體現(xiàn)著封裝的概念:你的身體把膀胱尿道等等這些尿的功能隱藏了起來,然后為你提供一個尿的接口就可以了(接口就是你的。。。,),你總不能把膀胱掛在身體外面,上廁所的時候就跟別人炫耀:hi,man,你瞅我的膀胱,看看我是怎么尿的。還有你的頭把你的腦子封裝到了腦殼里,然后提供了眼睛這個接口....

提示:在編程語言里,對外提供的接口,就是函數(shù),稱為接口函數(shù),這與接口的概念還不一樣,接口代表一組接口函數(shù)的集合體,后續(xù)我們將介紹到。

6.3 封裝分為兩個層面

封裝其實分為兩個層面,但很多資料中都混在一起去說,很容易讓初學(xué)者懵逼:

第一個層面的封裝(什么都不用做):創(chuàng)建類和對象會分別創(chuàng)建二者的名稱空間,我們只能用類名.或者obj.的方式去訪問里面的名字,這本身就是一種封裝

>>> r1.nickname '草叢倫' >>> Riven.camp 'Noxus'

注意:對于這一層面的封裝(隱藏),類名.和實例名.就是訪問隱藏屬性的接口(或者叫入口)

第二個層面的封裝:類中把某些屬性和方法隱藏起來(或者說定義成私有的),只在類的內(nèi)部使用、外部無法訪問,或者留下少量接口(函數(shù))供外部訪問。

在python中用雙下劃線的方式實現(xiàn)隱藏屬性(設(shè)置成私有的)

類中所有雙下劃線開頭的名稱如__x都會自動變形成:_類名__x的形式:

class A:__N=0 #類的數(shù)據(jù)屬性就應(yīng)該是共享的,但是語法上是可以把類的數(shù)據(jù)屬性設(shè)置成私有的如__N,會變形為_A__Ndef __init__(self):self.__X=10 #變形為self._A__Xdef __foo(self): #變形為_A__fooprint('from A')def bar(self):self.__foo() #只有在類內(nèi)部才可以通過__foo的形式訪問到.

這種自動變形的特點:

1.類中定義的__x只能在內(nèi)部使用,如self.__x,引用的就是變形的結(jié)果

2.這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。

2.在子類定義的__x不會覆蓋在父類定義的__x,因為子類中變形成了:_子類名__x,而父類中變形成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。

注意:對于這一層面的封裝(隱藏),我們需要在類中定義一個函數(shù)(接口函數(shù))在它內(nèi)部訪問被隱藏的屬性,然后外部就可以使用了

也可以用6.4所講的特性property來解決,即將介紹

? 這種變形需要注意的問題是:

1.這種機(jī)制也并沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名就可以拼出名字:_類名__屬性,然后就可以訪問了,如a._A__N

>>> a=A() >>> a._A__N 0 >>> a._A__X 10 >>> A._A__N 0

2.變形的過程只在類的定義是發(fā)生一次,在定義后的賦值操作,不會變形

3.在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為私有的

#正常情況 >>> class A: ... def fa(self): ... print('from A') ... def test(self): ... self.fa() ... >>> class B(A): ... def fa(self): ... print('from B') ... >>> b=B() >>> b.test() from B #把fa定義成私有的,即__fa >>> class A: ... def __fa(self): #在定義時就變形為_A__fa ... print('from A') ... def test(self): ... self.__fa() #只會與自己所在的類為準(zhǔn),即調(diào)用_A__fa ... >>> class B(A): ... def __fa(self): ... print('from B') ... >>> b=B() >>> b.test() from A

python并不會真的阻止你訪問私有的屬性,模塊也遵循這種約定,如果模塊名以單下劃線開頭,那么from module import *時不能被導(dǎo)入,但是你from module import _private_module依然是可以導(dǎo)入的

其實很多時候你去調(diào)用一個模塊的功能時會遇到單下劃線開頭的(socket._socket,sys._home,sys._clear_type_cache),這些都是私有的,原則上是供內(nèi)部調(diào)用的,作為外部的你,一意孤行也是可以用的,只不過顯得稍微傻逼一點點

6.4 特性(property)

1 什么是特性property

property是一種特殊的屬性,訪問它時會執(zhí)行一段功能(函數(shù))然后返回值

import math class Circle:def __init__(self,radius): #圓的半徑radiusself.radius=radius@propertydef area(self):return math.pi * self.radius**2 #計算面積@propertydef perimeter(self):return 2*math.pi*self.radius #計算周長c=Circle(10) print(c.radius) print(c.area) #可以向訪問數(shù)據(jù)屬性一樣去訪問area,會觸發(fā)一個函數(shù)的執(zhí)行,動態(tài)計算出一個值 print(c.perimeter) #同上 ''' 輸出結(jié)果: 10 314.1592653589793 62.83185307179586 '''

注意:此時的特性arear和perimeter不能被賦值

c.area=3 #為特性area賦值 ''' 拋出異常: AttributeError: can't set attribute '''

2 為什么要用property

將一個類的函數(shù)定義成特性以后,對象再去使用的時候obj.name,根本無法察覺自己的name是執(zhí)行了一個函數(shù)然后計算出來的,這種特性的使用方式遵循了統(tǒng)一訪問的原則

除此之外,看下

ps:面向?qū)ο蟮姆庋b有三種方式: 【public】 這種其實就是不封裝,是對外公開的 【protected】 這種封裝方式對外不公開,但對朋友(friend)或者子類(形象的說法是“兒子”,但我不知道為什么大家 不說“女兒”,就像“parent”本來是“父母”的意思,但中文都是叫“父類”)公開 【private】 這種封裝對誰都不公開

python并沒有在語法上把它們?nèi)齻€內(nèi)建到自己的class機(jī)制中,在C++里一般會將所有的所有的數(shù)據(jù)都設(shè)置為私有的,然后提供set和get方法(接口)去設(shè)置和獲取,在python中通過property方法可以實現(xiàn)

class Foo:def __init__(self,val):self.__NAME=val #將所有的數(shù)據(jù)屬性都隱藏起來@propertydef name(self):return self.__NAME #obj.name訪問的是self.__NAME(這也是真實值的存放位置)@name.setterdef name(self,value):if not isinstance(value,str): #在設(shè)定值之前進(jìn)行類型檢查raise TypeError('%s must be str' %value)self.__NAME=value #通過類型檢查后,將值value存放到真實的位置self.__NAME@name.deleterdef name(self):raise TypeError('Can not delete')f=Foo('egon') print(f.name) # f.name=10 #拋出異常'TypeError: 10 must be str' del f.name #拋出異常'TypeError: Can not delete view code class Foo:def __init__(self,val):self.__NAME=val #將所有的數(shù)據(jù)屬性都隱藏起來def getname(self):return self.__NAME #obj.name訪問的是self.__NAME(這也是真實值的存放位置)def setname(self,value):if not isinstance(value,str): #在設(shè)定值之前進(jìn)行類型檢查raise TypeError('%s must be str' %value)self.__NAME=value #通過類型檢查后,將值value存放到真實的位置self.__NAMEdef delname(self):raise TypeError('Can not delete')name=property(getname,setname,delname) #不如裝飾器的方式清晰 view code

6.5 封裝與擴(kuò)展性

封裝在于明確區(qū)分內(nèi)外,使得類實現(xiàn)者可以修改封裝內(nèi)的東西而不影響外部調(diào)用者的代碼;而外部使用用者只知道一個接口(函數(shù)),只要接口(函數(shù))名、參數(shù)不變,使用者的代碼永遠(yuǎn)無需改變。這就提供一個良好的合作基礎(chǔ)——或者說,只要接口這個基礎(chǔ)約定不變,則代碼改變不足為慮。

#類的設(shè)計者 class Room:def __init__(self,name,owner,width,length,high):self.name=nameself.owner=ownerself.__width=widthself.__length=lengthself.__high=highdef tell_area(self): #對外提供的接口,隱藏了內(nèi)部的實現(xiàn)細(xì)節(jié),此時我們想求的是面積return self.__width * self.__length view code #使用者 >>> r1=Room('臥室','egon',20,20,20) >>> r1.tell_area() #使用者調(diào)用接口tell_area 400 view code #類的設(shè)計者,輕松的擴(kuò)展了功能,而類的使用者完全不需要改變自己的代碼 class Room:def __init__(self,name,owner,width,length,high):self.name=nameself.owner=ownerself.__width=widthself.__length=lengthself.__high=highdef tell_area(self): #對外提供的接口,隱藏內(nèi)部實現(xiàn),此時我們想求的是體積,內(nèi)部邏輯變了,只需求修該下列一行就可以很簡答的實現(xiàn),而且外部調(diào)用感知不到,仍然使用該方法,但是功能已經(jīng)變了return self.__width * self.__length * self.__high view code

對于仍然在使用tell_area接口的人來說,根本無需改動自己的代碼,就可以用上新功能

>>> r1.tell_area() 8000

七 靜態(tài)方法和類方法

通常情況下,在類中定義的所有函數(shù)(注意了,這里說的就是所有,跟self啥的沒關(guān)系,self也只是一個再普通不過的參數(shù)而已)都是對象的綁定方法,對象在調(diào)用綁定方法時會自動將自己作為參數(shù)傳遞給方法的第一個參數(shù)。除此之外還有兩種常見的方法:靜態(tài)方法和類方法,二者是為類量身定制的,但是實例非要使用,也不會報錯,后續(xù)將介紹。

1 靜態(tài)方法

是一種普通函數(shù),位于類定義的命名空間中,不會對任何實例類型進(jìn)行操作,python為我們內(nèi)置了函數(shù)staticmethod來把類中的函數(shù)定義成靜態(tài)方法

class Foo:def spam(x,y,z): #類中的一個函數(shù),千萬不要懵逼,self和x啥的沒有不同都是參數(shù)名print(x,y,z)spam=staticmethod(spam) #把spam函數(shù)做成靜態(tài)方法

基于之前所學(xué)裝飾器的知識,@staticmethod 等同于spam=staticmethod(spam),于是

class Foo:@staticmethod #裝飾器def spam(x,y,z):print(x,y,z)

使用演示

print(type(Foo.spam)) #類型本質(zhì)就是函數(shù) Foo.spam(1,2,3) #調(diào)用函數(shù)應(yīng)該有幾個參數(shù)就傳幾個參數(shù)f1=Foo() f1.spam(3,3,3) #實例也可以使用,但通常靜態(tài)方法都是給類用的,實例在使用時喪失了自動傳值的機(jī)制''' <class 'function'> 1 2 3 3 3 3 '''

應(yīng)用場景:編寫類時需要采用很多不同的方式來創(chuàng)建實例,而我們只有一個__init__函數(shù),此時靜態(tài)方法就派上用場了

class Date:def __init__(self,year,month,day):self.year=yearself.month=monthself.day=day@staticmethoddef now(): #用Date.now()的形式去產(chǎn)生實例,該實例用的是當(dāng)前時間t=time.localtime() #獲取結(jié)構(gòu)化的時間格式return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建實例并且返回@staticmethoddef tomorrow():#用Date.tomorrow()的形式去產(chǎn)生實例,該實例用的是明天的時間t=time.localtime(time.time()+86400)return Date(t.tm_year,t.tm_mon,t.tm_mday)a=Date('1987',11,27) #自己定義時間 b=Date.now() #采用當(dāng)前時間 c=Date.tomorrow() #采用明天的時間print(a.year,a.month,a.day) print(b.year,b.month,b.day) print(c.year,c.month,c.day)

2 類方法

  類方法是給類用的,類在使用時會將類本身當(dāng)做參數(shù)傳給類方法的第一個參數(shù),python為我們內(nèi)置了函數(shù)classmethod來把類中的函數(shù)定義成類方法

class A:x=1@classmethoddef test(cls):print(cls,cls.x)class B(A):x=2 B.test()''' 輸出結(jié)果: <class '__main__.B'> 2 '''

 應(yīng)用場景:

import time class Date:def __init__(self,year,month,day):self.year=yearself.month=monthself.day=day@staticmethoddef now():t=time.localtime()return Date(t.tm_year,t.tm_mon,t.tm_mday)class EuroDate(Date):def __str__(self):return 'year:%s month:%s day:%s' %(self.year,self.month,self.day)e=EuroDate.now() print(e) #我們的意圖是想觸發(fā)EuroDate.__str__,但是結(jié)果為 ''' 輸出結(jié)果: <__main__.Date object at 0x1013f9d68> '''

因為e就是用Date類產(chǎn)生的,所以根本不會觸發(fā)EuroDate.__str__,解決方法就是用classmethod

import time class Date:def __init__(self,year,month,day):self.year=yearself.month=monthself.day=day# @staticmethod# def now():# t=time.localtime()# return Date(t.tm_year,t.tm_mon,t.tm_mday)@classmethod #改成類方法def now(cls):t=time.localtime()return cls(t.tm_year,t.tm_mon,t.tm_mday) #哪個類來調(diào)用,即用哪個類cls來實例化class EuroDate(Date):def __str__(self):return 'year:%s month:%s day:%s' %(self.year,self.month,self.day)e=EuroDate.now() print(e) #我們的意圖是想觸發(fā)EuroDate.__str__,此時e就是由EuroDate產(chǎn)生的,所以會如我們所愿 ''' 輸出結(jié)果: year:2017 month:3 day:3 '''

強(qiáng)調(diào),注意注意注意:靜態(tài)方法和類方法雖然是給類準(zhǔn)備的,但是如果實例去用,也是可以用的,只不過實例去調(diào)用的時候容易讓人混淆,不知道你要干啥

x=e.now() #通過實例e去調(diào)用類方法也一樣可以使用,靜態(tài)方法也一樣 print(x) ''' 輸出結(jié)果: year:2017 month:3 day:3 '''

八 面向?qū)ο蟮能浖_發(fā)

很多人在學(xué)完了python的class機(jī)制之后,遇到一個生產(chǎn)中的問題,還是會懵逼,這其實太正常了,因為任何程序的開發(fā)都是先設(shè)計后編程,python的class機(jī)制只不過是一種編程方式,如果你硬要拿著class去和你的問題死磕,變得更加懵逼都是分分鐘的事,在以前,軟件的開發(fā)相對簡單,從任務(wù)的分析到編寫程序,再到程序的調(diào)試,可以由一個人或一個小組去完成。但是隨著軟件規(guī)模的迅速增大,軟件任意面臨的問題十分復(fù)雜,需要考慮的因素太多,在一個軟件中所產(chǎn)生的錯誤和隱藏的錯誤、未知的錯誤可能達(dá)到驚人的程度,這也不是在設(shè)計階段就完全解決的。

??? 所以軟件的開發(fā)其實一整套規(guī)范,我們所學(xué)的只是其中的一小部分,一個完整的開發(fā)過程,需要明確每個階段的任務(wù),在保證一個階段正確的前提下再進(jìn)行下一個階段的工作,稱之為軟件工程

??? 面向?qū)ο蟮能浖こ贪ㄏ旅鎺讉€部:

1.面向?qū)ο蠓治?#xff08;object oriented analysis ,OOA)

??? 軟件工程中的系統(tǒng)分析階段,要求分析員和用戶結(jié)合在一起,對用戶的需求做出精確的分析和明確的表述,從大的方面解析軟件系統(tǒng)應(yīng)該做什么,而不是怎么去做。面向?qū)ο蟮姆治鲆凑彰嫦驅(qū)ο蟮母拍詈头椒?#xff0c;在對任務(wù)的分析中,從客觀存在的事物和事物之間的關(guān)系,貴南出有關(guān)的對象(對象的‘特征’和‘技能’)以及對象之間的聯(lián)系,并將具有相同屬性和行為的對象用一個類class來標(biāo)識。

??? 建立一個能反映這是工作情況的需求模型,此時的模型是粗略的。

2 面向?qū)ο笤O(shè)計(object oriented design,OOD)

??? 根據(jù)面向?qū)ο蠓治鲭A段形成的需求模型,對每一部分分別進(jìn)行具體的設(shè)計。

??? 首先是類的設(shè)計,類的設(shè)計可能包含多個層次(利用繼承與派生機(jī)制)。然后以這些類為基礎(chǔ)提出程序設(shè)計的思路和方法,包括對算法的設(shè)計。

??? 在設(shè)計階段并不牽涉任何一門具體的計算機(jī)語言,而是用一種更通用的描述工具(如偽代碼或流程圖)來描述

3 面向?qū)ο缶幊?#xff08;object oriented programming,OOP)

??? 根據(jù)面向?qū)ο笤O(shè)計的結(jié)果,選擇一種計算機(jī)語言把它寫成程序,可以是python

4 面向?qū)ο鬁y試(object oriented test,OOT)

??? 在寫好程序后交給用戶使用前,必須對程序進(jìn)行嚴(yán)格的測試,測試的目的是發(fā)現(xiàn)程序中的錯誤并修正它。

??? 面向?qū)Φ臏y試是用面向?qū)ο蟮姆椒ㄟM(jìn)行測試,以類作為測試的基本單元。

5 面向?qū)ο缶S護(hù)(object oriendted soft maintenance,OOSM)

??? 正如對任何產(chǎn)品都需要進(jìn)行售后服務(wù)和維護(hù)一樣,軟件在使用時也會出現(xiàn)一些問題,或者軟件商想改進(jìn)軟件的性能,這就需要修改程序。

??? 由于使用了面向?qū)ο蟮姆椒ㄩ_發(fā)程序,使用程序的維護(hù)比較容易。

??? 因為對象的封裝性,修改一個對象對其他的對象影響很小,利用面向?qū)ο蟮姆椒ňS護(hù)程序,大大提高了軟件維護(hù)的效率,可擴(kuò)展性高。

??? 在面向?qū)ο蠓椒ㄖ?#xff0c;最早發(fā)展的肯定是面向?qū)ο缶幊?OOP),那時OOA和OOD都還沒有發(fā)展起來,因此程序設(shè)計者為了寫出面向?qū)ο蟮某绦?#xff0c;還必須深入到分析和設(shè)計領(lǐng)域,尤其是設(shè)計領(lǐng)域,那時的OOP實際上包含了現(xiàn)在的OOD和OOP兩個階段,這對程序設(shè)計者要求比較高,許多人感到很難掌握。

??? 現(xiàn)在設(shè)計一個大的軟件,是嚴(yán)格按照面向?qū)ο筌浖こ痰?個階段進(jìn)行的,這個5個階段的工作不是由一個人從頭到尾完成的,而是由不同的人分別完成,這樣OOP階段的任務(wù)就比較簡單了。程序編寫者只需要根據(jù)OOd提出的思路,用面向?qū)ο笳Z言編寫出程序既可。

??? 在一個大型軟件開發(fā)過程中,OOP只是很小的一個部分。

??? 對于全棧開發(fā)的你來說,這五個階段都有了,對于簡單的問題,不必嚴(yán)格按照這個5個階段進(jìn)行,往往由程序設(shè)計者按照面向?qū)ο蟮姆椒ㄟM(jìn)行程序設(shè)計,包括類的設(shè)計和程序的設(shè)計

九 小白容易犯的錯誤

1.面向?qū)ο蟮某绦蛟O(shè)計看起來高大上,所以我在編程時就應(yīng)該保證通篇class,這樣寫出的程序一定是好的程序(面向?qū)ο笾贿m合那些可擴(kuò)展性要求比較高的場景)

2.很多人喜歡說面向?qū)ο笕筇匦?#xff08;這是從哪傳出來的,封裝,多態(tài),繼承?漏洞太多太多,好吧暫且稱為三大特性),那么我在基于面向?qū)ο缶幊虝r,我一定要讓我定義的類中完整的包含這三種特性,這樣寫肯定是好的程序

好家伙,我說降龍十八掌有十八掌,那么你每次跟人干仗都要從第一掌打到第18掌這才顯得你會了是么,我來一萬個人你需要打10000*18掌對么,傻叉

3.類有類屬性,實例有實例屬性,所以我們在定義class時一定要定義出那么幾個類屬性,想不到怎么辦,那就使勁的想,定義的越多越牛逼

這就犯了一個嚴(yán)重的錯誤,程序越早面向?qū)ο?#xff0c;死的越早,為啥面向?qū)ο?#xff0c;因為我們要將數(shù)據(jù)與功能結(jié)合到一起,程序整體的結(jié)構(gòu)都沒有出來,或者說需要考慮的問題你都沒有搞清楚個八九不離十,你就開始面向?qū)ο罅?#xff0c;這就導(dǎo)致了,你在那里干想,自以為想通了,定義了一堆屬性,結(jié)果后來又都用不到,或者想不通到底應(yīng)該定義啥,那就一直想吧,想著想著就瘋了。

你見過哪家公司要開發(fā)一個軟件,上來就開始寫,肯定是頻繁的開會討論計劃,請看第八節(jié)

4.既然這么麻煩,那么我徹底解脫了,我們不要用面向?qū)ο缶幊塘?#xff0c;你啊,你有大才,你能成事啊,傻叉。

十 python中關(guān)于OOP的常用術(shù)語

抽象/實現(xiàn)

抽象指對現(xiàn)實世界問題和實體的本質(zhì)表現(xiàn),行為和特征建模,建立一個相關(guān)的子集,可以用于 繪程序結(jié)構(gòu),從而實現(xiàn)這種模型。抽象不僅包括這種模型的數(shù)據(jù)屬性,還定義了這些數(shù)據(jù)的接口。

對某種抽象的實現(xiàn)就是對此數(shù)據(jù)及與之相關(guān)接口的現(xiàn)實化(realization)。現(xiàn)實化這個過程對于客戶 程序應(yīng)當(dāng)是透明而且無關(guān)的。?

封裝/接口

封裝描述了對數(shù)據(jù)/信息進(jìn)行隱藏的觀念,它對數(shù)據(jù)屬性提供接口和訪問函數(shù)。通過任何客戶端直接對數(shù)據(jù)的訪問,無視接口,與封裝性都是背道而馳的,除非程序員允許這些操作。作為實現(xiàn)的 一部分,客戶端根本就不需要知道在封裝之后,數(shù)據(jù)屬性是如何組織的。在Python中,所有的類屬性都是公開的,但名字可能被“混淆”了,以阻止未經(jīng)授權(quán)的訪問,但僅此而已,再沒有其他預(yù)防措施了。這就需要在設(shè)計時,對數(shù)據(jù)提供相應(yīng)的接口,以免客戶程序通過不規(guī)范的操作來存取封裝的數(shù)據(jù)屬性。

注意:封裝絕不是等于“把不想讓別人看到、以后可能修改的東西用private隱藏起來”

真正的封裝是,經(jīng)過深入的思考,做出良好的抽象,給出“完整且最小”的接口,并使得內(nèi)部細(xì)節(jié)可以對外透明

(注意:對外透明的意思是外部調(diào)用者可以順利的得到自己想要的任何功能,完全意識不到內(nèi)部細(xì)節(jié)的存在)

合成

合成擴(kuò)充了對類的 述,使得多個不同的類合成為一個大的類,來解決現(xiàn)實問題。合成 述了 一個異常復(fù)雜的系統(tǒng),比如一個類由其它類組成,更小的組件也可能是其它的類,數(shù)據(jù)屬性及行為, 所有這些合在一起,彼此是“有一個”的關(guān)系。

派生/繼承/繼承結(jié)構(gòu)

派生描述了子類衍生出新的特性,新類保留已存類類型中所有需要的數(shù)據(jù)和行為,但允許修改或者其它的自定義操作,都不會修改原類的定義。
繼承描述了子類屬性從祖先類繼承這樣一種方式
繼承結(jié)構(gòu)表示多“代”派生,可以述成一個“族譜”,連續(xù)的子類,與祖先類都有關(guān)系。

泛化/特化

基于繼承
泛化表示所有子類與其父類及祖先類有一樣的特點。
特化描述所有子類的自定義,也就是,什么屬性讓它與其祖先類不同。

多態(tài)與多態(tài)性

多態(tài)指的是同一種事物的多種狀態(tài):水這種事物有多種不同的狀態(tài):冰,水蒸氣

多態(tài)性的概念指出了對象如何通過他們共同的屬性和動作來操作及訪問,而不需考慮他們具體的類。

冰,水蒸氣,都繼承于水,它們都有一個同名的方法就是變成云,但是冰.變云(),與水蒸氣.變云()是截然不同的過程,雖然調(diào)用的方法都一樣

自省/反射

自省也稱作反射,這個性質(zhì)展示了某對象是如何在運行期取得自身信息的。如果傳一個對象給你,你可以查出它有什么能力,這是一項強(qiáng)大的特性。如果Python不支持某種形式的自省功能,dir和type內(nèi)建函數(shù),將很難正常工作。還有那些特殊屬性,像__dict__,__name__及__doc__

轉(zhuǎn)載于:https://www.cnblogs.com/can-H/articles/6506475.html

總結(jié)

以上是生活随笔為你收集整理的08-面向对象----的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

久久手机免费视频 | 黄色一区二区在线观看 | 中文字幕一区二区三区四区 | 国产精品麻 | 精品国产一区二区三区四区在线观看 | 日韩电影久久 | 亚洲年轻女教师毛茸茸 | 视频三区在线 | 精品国产欧美 | 成人污视频在线观看 | 日本一区二区免费在线观看 | 国产日产av | 久久人人爽人人人人片 | 国产免费看| 一级a性色生活片久久毛片波多野 | 中文字幕在线久一本久 | 99视频在线免费观看 | 激情深爱五月 | 欧美精品国产精品 | 在线日韩亚洲 | 黄色一级在线观看 | 欧美精品亚洲精品日韩精品 | 99精品在线 | 免费av看片| 国产成人精品一区二区三区福利 | 中文字幕在线国产精品 | 亚洲精品视频免费 | 国内精品久久久久久久影视麻豆 | 国产v在线播放 | 欧美日本不卡视频 | 日韩一区二区三 | 最新av网址在线观看 | 免费一级特黄录像 | av电影在线播放 | 亚洲色图av | 激情综合啪啪 | 国产一级不卡视频 | 狠狠干天天操 | 亚洲人片在线观看 | 一区在线观看视频 | 久久久久久不卡 | 亚洲精品电影在线 | 成人国产精品一区 | 日韩精品视频在线观看网址 | 亚洲女人av | 国产一区二区三区四区在线 | 日韩在线在线 | 超碰99人人 | 久久久久福利视频 | 97精品国产97久久久久久免费 | 久久久这里有精品 | 在线精品在线 | 欧美一级日韩免费不卡 | 国产精品观看在线亚洲人成网 | 天堂av在线网址 | 色中色综合 | 久久精品日产第一区二区三区乱码 | 国产精品理论片在线观看 | 国产又黄又爽又猛视频日本 | 国产亚洲精品久久 | 国产精品黄色av | 久久三级视频 | 91日韩免费 | 人人射人人爽 | 国产欧美精品在线观看 | 在线欧美最极品的av | 五月婷婷综合激情 | 亚洲精品高清一区二区三区四区 | 国产一级视频在线 | 91精品国产91久久久久久三级 | 97日日碰人人模人人澡分享吧 | 99久久精品国产一区二区三区 | 日韩电影精品 | 天天爱天天操天天射 | 久久99精品波多结衣一区 | 国产精品久久99综合免费观看尤物 | 国产精品久久久久久久久久直播 | 一级黄网 | 亚洲最新av在线网址 | 中文在线√天堂 | 天天射天天爽 | 午夜在线免费视频 | 欧美夫妻生活视频 | 国产精品观看 | 精品主播网红福利资源观看 | 中文字幕文字幕一区二区 | 骄小bbw搡bbbb揉bbbb | 91精品国产一区二区在线观看 | 在线观看成人小视频 | 一级做a爱片性色毛片www | 国产综合在线观看视频 | 日韩成人免费在线 | 国产一区二区久久精品 | 日批网站在线观看 | 久久综合九色欧美综合狠狠 | 久久网站最新地址 | 成人a级免费视频 | 精品国产亚洲一区二区麻豆 | 免费av片在线 | 国产精品中文 | 国产视频精选在线 | 99久久9 | 久久理论电影网 | 在线观看亚洲精品 | 国产精品原创 | 国产成人黄色网址 | 91中文视频 | 天堂久色| 婷婷网五月天 | 久久精品a| 欧美在线日韩在线 | 91一区二区三区在线观看 | 国产精品一区二区久久精品爱涩 | 亚洲香蕉在线观看 | 日韩无在线 | 日韩av一区二区三区在线观看 | 香蕉免费在线 | 国产精品一区二区精品视频免费看 | 97看片 | 婷婷伊人五月 | 精品中文字幕在线 | 日韩视频免费观看高清完整版在线 | 国产91在线免费视频 | 中文字幕麻豆 | 91自拍91 | 日韩av免费大片 | 美女精品久久久 | 一级黄色片在线免费观看 | 国产精品女视频 | 日韩成人精品一区二区 | 999ZYZ玖玖资源站永久 | 美女在线观看av | 久久久久久久国产精品视频 | 久久精品免费看 | 91视频最新网址 | 狠狠狠狠狠操 | 精品国产一区二区三区在线 | 五月婷婷.com | 亚洲国产成人精品在线 | 香蕉久草 | 99精品一区二区三区 | 国产精品一区二区av日韩在线 | 精品免费久久久久 | 97伊人网| 一区二区精品在线观看 | 久久免费看a级毛毛片 | 天天干天天插 | 天天干天天射天天操 | 国产xvideos免费视频播放 | 中文字幕欲求不满 | 亚洲精品国精品久久99热一 | 九九热视频在线播放 | 久久乐九色婷婷综合色狠狠182 | 日韩在线观看中文字幕 | 一区二区三区国产欧美 | 国产一区二区在线免费 | 精品免费视频123区 午夜久久成人 | av中文在线播放 | 人人舔人人干 | 亚洲狠狠婷婷 | 亚洲精品在线一区二区 | 免费福利视频网 | 黄色在线观看免费网站 | 在线99视频 | 成人免费网视频 | www.在线观看av | 天天想夜夜操 | 不卡中文字幕在线 | 国产日产精品久久久久快鸭 | 精品久久国产一区 | 91视频久久久久久 | 婷婷亚洲综合 | 亚洲综合欧美精品电影 | 久草视频中文在线 | 国产精品亚洲人在线观看 | 亚州欧美精品 | 99热这里是精品 | 91亚色视频在线观看 | av免费观看网站 | 亚洲国产播放 | 最新精品国产 | 精品91在线| 亚洲精品乱码久久久久久蜜桃欧美 | 国产日韩欧美在线影视 | 中文字幕中文字幕 | 国产高清av免费在线观看 | 91色影院| 西西www4444大胆在线 | 久久久久久麻豆 | 日本动漫做毛片一区二区 | 在线 高清 中文字幕 | 久久视频中文字幕 | 黄色精品一区二区 | 久久久久久久福利 | 亚洲精品乱码久久久久久高潮 | 欧洲精品视频一区 | 天天色成人网 | 亚洲免费在线看 | 精品国产伦一区二区三区观看体验 | 91热在线| 91久久精品一区 | 国语麻豆 | 久久在现视频 | 国产精品刺激对白麻豆99 | 欧美最猛性xxxxx亚洲精品 | 91成品人影院 | 高清精品在线 | av在线超碰 | 国产一区久久久 | 中文字幕av在线 | 国产资源av | 在线免费观看麻豆视频 | 天天做日日爱夜夜爽 | 又大又硬又黄又爽视频在线观看 | 深爱五月激情五月 | 超碰在线亚洲 | 亚洲精品高清视频 | 九九热精品视频在线播放 | 欧美日韩3p | 91成人亚洲| 国产精品9999久久久久仙踪林 | 日韩电影在线观看中文字幕 | 91精品一| 国产一区二区三区久久久 | 日本中文不卡 | 九九热只有精品 | 91麻豆精品国产91久久久使用方法 | 在线免费精品视频 | 狠狠久久 | 国产精品99蜜臀久久不卡二区 | 天天搞天天干天天色 | 婷婷丁香在线观看 | 成人av在线影院 | 国产伦精品一区二区三区照片91 | 成人一级黄色片 | 又色又爽又黄高潮的免费视频 | 久久国内免费视频 | 91在线精品秘密一区二区 | 久久不卡视频 | 91网址在线看 | 三级黄免费看 | 美女黄久久 | 久久久久久国产一区二区三区 | 欧美人牲 | 亚洲成人国产精品 | 免费看片黄色 | 国内成人精品视频 | 日韩有码在线播放 | 欧美精品亚州精品 | 伊人亚洲综合网 | 香蕉在线视频观看 | 成人在线播放免费观看 | 久久久久综合精品福利啪啪 | 亚洲激情视频 | 97av精品| 黄色网大全| 91爱爱网址 | 免费亚洲视频在线观看 | 国产亚洲人成网站在线观看 | 久久视频免费看 | 国产精品久久久久久久久久免费看 | 久久手机免费观看 | 伊人婷婷 | 欧美成人亚洲成人 | av在线看片| 丁香久久久 | 久久精品电影院 | 国产一级高清 | 亚洲视频久久久 | 97自拍超碰 | 亚洲午夜激情网 | 在线看国产视频 | 91麻豆精品国产91久久久使用方法 | 亚洲精品 在线视频 | 欧美精品亚洲二区 | 五月婷婷操 | 久久久久草 | 99精品色| 国产 成人 久久 | 天天色天天骑天天射 | 狠狠色婷婷丁香六月 | 日韩电影精品一区 | 欧美一区二区三区在线视频观看 | 国产一区二区日本 | 国产日产精品一区二区三区四区的观看方式 | 久久视| 精品国产乱子伦一区二区 | 国产精品日韩久久久久 | 中文字幕在线视频一区 | 久草精品在线观看 | 中国美女一级看片 | 97人人人人| 99精品热视频只有精品10 | 黄色免费网 | 九九久久精品视频 | 欧美精品国产综合久久 | 日日日视频 | 蜜桃传媒一区二区 | 天天操夜夜操夜夜操 | 日韩天堂在线观看 | 欧美日本啪啪无遮挡网站 | 久久综合久久综合久久 | 久久久久成 | 国产中文字幕一区二区 | 字幕网资源站中文字幕 | 97超碰免费在线 | 国产剧情一区在线 | av手机在线播放 | 国产精品精品国产婷婷这里av | av一级免费 | 成人一级在线 | 精品9999 | 国产一区二区久久久久 | 青青草国产精品 | 日本不卡123 | 国产精品久久久久久电影 | 91亚洲精品国偷拍 | 天堂va欧美va亚洲va老司机 | 久久人人爽人人爽人人片av软件 | 国产一区二区三区免费在线 | www黄色av | 欧美日韩有码 | 黄色福利视频网站 | 亚洲自拍自偷 | 日韩有码中文字幕在线 | 欧美日韩xxx| 亚洲一级电影在线观看 | 国产999精品视频 | 国产高清无线码2021 | 五月天视频网 | 亚洲天堂视频在线 | 国产又黄又猛又粗 | 免费黄色小网站 | 波多野结衣在线观看一区二区三区 | 国产精品在线看 | 国产婷婷| 伊人久久精品久久亚洲一区 | 天天干天天摸 | 国内精品久久久 | 亚洲精品在线免费看 | 亚洲做受高潮欧美裸体 | 久久精品99国产 | 成人在线视频网 | a级片韩国| 国产日韩视频在线播放 | 久草视频一区 | 99这里只有精品视频 | 一区二区三区日韩精品 | 久久久国产在线视频 | 欧美日韩高清不卡 | 九九九九热精品免费视频点播观看 | 开心激情婷婷 | 超薄丝袜一二三区 | 久久午夜网 | 国产精品乱看 | 欧美一区二区在线看 | 在线日本v二区不卡 | 天天躁天天狠天天透 | 久久99久久99免费视频 | 最近免费观看的电影完整版 | 久草久草在线 | 亚洲最新毛片 | 国产成人在线播放 | 夜色.com| 成人av资源站 | 欧美日韩在线免费观看视频 | 91传媒视频在线观看 | 五月香婷 | 亚洲精品一区二区三区新线路 | 欧美在线观看视频 | 婷婷午夜激情 | 欧美91视频| 最新中文字幕视频 | 天天操天天射天天爱 | 亚洲精品乱码久久久久久9色 | 一区二区三区手机在线观看 | 免费成人在线观看视频 | 欧美永久视频 | 麻豆视频在线播放 | 在线亚洲午夜片av大片 | 日本在线观看视频一区 | 黄色av成人在线观看 | 久久99视频免费观看 | 91在线精品观看 | 国产精品久久久久久久久搜平片 | 色播五月激情五月 | 国产高清小视频 | 日本九九视频 | 日日精品 | 99精品一区 | 国产精品久久久久久一区二区 | 91理论片午午伦夜理片久久 | 美女视频永久黄网站免费观看国产 | 亚洲欧洲精品一区二区 | 久久久久免费精品国产 | 黄网站色欧美视频 | 国产一区二区三区高清播放 | 国产 日韩 欧美 自拍 | 五月婷婷影院 | 九九九热| 国产不卡一区二区视频 | 欧美一级黄色网 | 日日日干| 婷婷色在线资源 | 久久久国产精品久久久 | 日韩电影黄色 | 韩日三级在线 | 亚洲国产日韩欧美 | 久久伦理| 国产精品免费在线观看视频 | 中午字幕在线 | 伊人狠狠色丁香婷婷综合 | 久久国产手机看片 | 97av精品 | 懂色av一区二区在线播放 | 九九免费在线观看视频 | 毛片精品免费在线观看 | 亚洲国产免费av | 91av中文| 在线观看视频亚洲 | 亚洲a在线观看 | 日日干天天 | 中文日韩在线视频 | 亚洲欧美国产精品 | 激情综合五月婷婷 | 国产久草在线 | 国产 视频 久久 | 亚洲高清在线精品 | av中文字幕不卡 | 在线观看成人小视频 | 国产系列在线观看 | 国产精品mv | 激情综合网五月婷婷 | 国产免码va在线观看免费 | 91观看视频 | 一区二区三区福利 | 欧美精品午夜 | 国产一区av在线 | 伊人伊成久久人综合网小说 | 91视频免费| 久久久久久久久艹 | 欧美一级片在线观看视频 | 六月激情 | 精品超碰 | 国产精品99免费看 | 亚洲精品在线观看视频 | 精品美女久久久久久免费 | 久久久久久免费视频 | 亚洲欧洲美洲av | 国内三级在线 | 黄污视频网站大全 | 久久少妇免费视频 | 久草在线免费在线观看 | 日韩黄色一区 | 在线色吧| 久久99国产视频 | 2021国产精品 | 日韩videos| 色狠狠综合天天综合综合 | av电影中文字幕 | 一区免费观看 | 91av电影在线| 国产视频18 | 夜夜操狠狠干 | 日韩一区二区三区高清在线观看 | 天天干干 | 伊人五月天婷婷 | 婷婷综合电影 | va视频在线观看 | 精品国产乱码久久久久久三级人 | 国产在线视频在线观看 | 精品国产电影一区二区 | 久久精品香蕉视频 | 高清av影院 | 久久公开视频 | www.在线看片.com| 91在线超碰 | 久久久久亚洲最大xxxx | 欧美精品乱码久久久久久按摩 | 中文字幕乱在线伦视频中文字幕乱码在线 | 视频成人永久免费视频 | 欧美精品久久久 | 国产精品久久久网站 | 91麻豆精品国产91久久久无限制版 | 亚洲精品视频在 | 国产传媒中文字幕 | 中文字幕在线观看免费 | 玖玖视频国产 | 久久久国产精品人人片99精片欧美一 | 日韩欧美一区二区三区黑寡妇 | 婷婷.com| 国产福利91精品一区二区三区 | 久久a v视频 | 最新国产视频 | 91精品久久久久久久久 | 日本午夜免费福利视频 | 亚洲欧美乱综合图片区小说区 | 中文字幕欧美三区 | 草久热 | 香蕉91视频 | 欧美日韩aa | 国内99视频| 91在线你懂的 | 美女一区网站 | 久久久色 | 97国产精品久久 | 91精品在线视频 | 免费色视频网址 | 国产高清免费视频 | 亚洲视频 在线观看 | 毛片网在线 | 欧美乱淫视频 | 国产在线自 | 免费成人结看片 | 久久国产热视频 | 在线看片成人 | av中文字幕在线电影 | 夜夜视频 | 国产一区av在线 | 色噜噜狠狠色综合中国 | 激情五月播播久久久精品 | 午夜 免费 | 在线激情影院一区 | 激情电影影院 | 国产99久久久国产精品成人免费 | 国模一区二区三区四区 | 日韩欧美在线免费观看 | 免费毛片一区二区三区久久久 | 97超在线视频 | 成人在线免费看视频 | 人人爽久久久噜噜噜电影 | 最近久乱中文字幕 | 免费精品 | 成 人 黄 色 片 在线播放 | 在线看一区| 久久久久成人免费 | av高清免费在线 | 成人在线免费av | 精品久久一二三区 | 一级欧美日韩 | 视频91| 国产又黄又猛又粗 | 国产精品午夜在线观看 | 夜夜高潮夜夜爽国产伦精品 | 一级黄网| 国产成人精品av在线 | 新av在线| 精品1区2区| 夜夜操天天干 | 国产精品你懂的在线观看 | 国产日韩欧美在线播放 | 亚洲成人av在线播放 | 一区二区三区不卡在线 | 9幺看片 | 国产成人一区二区在线观看 | 欧美性色19p | 中文字幕日本特黄aa毛片 | 在线观看成人国产 | 最新动作电影 | 亚洲第一久久久 | 在线观看激情av | 日韩av三区 | 天天做日日爱夜夜爽 | 久久99九九99精品 | 国产精品视频久久久 | av电影在线不卡 | 欧美日韩国产区 | 欧美专区国产专区 | 中文字幕日韩有码 | 国产中文字幕国产 | 一区二区欧美激情 | av在线超碰 | 精品国产自在精品国产精野外直播 | 国产成人免费观看 | 久久天天躁夜夜躁狠狠躁2022 | 丝袜美腿在线播放 | 9999在线| 在线观看日韩专区 | 最近av在线| 怡红院av| 中文字幕第一页在线播放 | 国产精品久久久久999 | 亚洲欧美日韩中文在线 | 九色91在线 | 日韩 在线观看 | 青青色影院 | 日韩精品黄 | 999ZYZ玖玖资源站永久 | 天天色综合1 | 麻豆播放 | 黄色软件在线观看免费 | 99久久国产免费,99久久国产免费大片 | 欧美日韩高清一区 | 91大神电影| 国产亚洲综合精品 | av免费观看网站 | 亚洲综合丁香 | 久草在线免费色站 | 国产精品免费观看在线 | 一级一级一片免费 | 成人毛片在线观看 | 狠狠狠狠狠狠操 | 婷婷丁香久久五月婷婷 | 中文在线资源 | 97人人超碰在线 | 色老板在线视频 | av先锋中文字幕 | 91香蕉国产在线观看软件 | 国产最新网站 | 亚洲视频久久久久 | 国产最新91 | 九九免费精品视频在线观看 | 久草综合在线 | 国产精品v欧美精品v日韩 | 在线精品亚洲一区二区 | 在线观看成人小视频 | 日韩一区二区三区免费视频 | 成人国产精品av | 五月天丁香综合 | 国产精品理论片在线观看 | 成人国产精品免费 | 精品国产一区二区三区久久 | 爱干视频 | 蜜臀av性久久久久av蜜臀妖精 | 亚洲精品网站在线 | 日日草夜夜操 | 久久9999久久免费精品国产 | 日韩精品欧美一区 | 欧美日韩综合在线观看 | 韩日三级在线 | 97视频在线观看视频免费视频 | 国际精品久久久久 | 国产一区二区精 | 午夜精品久久久久99热app | 一区中文字幕在线观看 | 久久久久麻豆v国产 | 国产一区不卡在线 | 日本中文乱码卡一卡二新区 | av在线免费不卡 | 成人av影视观看 | 日本精品视频免费 | 久久久黄色免费网站 | 国产 中文 日韩 欧美 | 国产精品久久久久久久7电影 | 国产精品美女久久久久久免费 | 97视频在线免费观看 | 视频1区2区 | 丝袜美腿在线视频 | 国产精品123| 日韩精品电影在线播放 | 九九亚洲视频 | 日日干av | 激情综合六月 | 久久国产精品精品国产色婷婷 | 日韩系列在线 | 国产一级视屏 | 久久,天天综合 | 免费看一级特黄a大片 | 亚洲国产美女久久久久 | 不卡精品视频 | 99视频精品视频高清免费 | 久久免费视频一区 | 欧美日高清视频 | 国产黄色理论片 | 国产人在线成免费视频 | 九九涩涩av台湾日本热热 | 国产在线一区观看 | 中文字幕在线乱 | 碰超在线97人人 | 中文字幕av在线不卡 | 成人资源在线观看 | 日韩欧美大片免费观看 | 香蕉视频在线视频 | 五月天久久婷婷 | 精品国产视频一区 | 国产精品久久久久久妇 | 青青草久草在线 | 国产在线国偷精品产拍免费yy | 日本女人的性生活视频 | 啪啪肉肉污av国网站 | 日韩免费在线观看网站 | 亚洲精品国偷拍自产在线观看蜜桃 | 久久久久 | 久久亚洲综合色 | 香蕉视频在线网站 | 国产在线观看免费av | 国产色婷婷精品综合在线手机播放 | 亚洲日韩精品欧美一区二区 | 在线黄频| 久草在线精品观看 | 国语久久 | 丝袜美腿在线播放 | 六月丁香久久 | 91成人午夜| 热久久免费国产视频 | 日韩成人精品一区二区 | 国产精品美女网站 | 免费黄在线观看 | 亚洲欧美视频在线播放 | 欧美性黄网官网 | 99久久这里只有精品 | 久久久免费看片 | 日韩一二三区不卡 | 免费观看www视频 | 免费在线观看a v | 91香蕉视频色版 | 亚洲国产成人在线播放 | 一本色道久久综合亚洲二区三区 | 黄视频色网站 | 欧美高清成人 | 久久免费观看视频 | 久99久在线视频 | 亚州欧美精品 | 18久久久久 | 日韩精品视频免费专区在线播放 | 久久视频在线视频 | 伊甸园永久入口www 99热 精品在线 | 涩涩成人在线 | 日日天天av | 亚洲欧洲一区二区在线观看 | 久久久久视 | 激情五月婷婷丁香 | 狠狠操狠狠干天天操 | 欧美日韩a视频 | 伊人开心激情 | 九九日韩| 99国产视频 | 国产精品日韩精品 | 亚洲理论在线观看电影 | 狠狠操狠狠干天天操 | 一区二区视频在线播放 | 在线观看免费色 | 婷婷综合网| 久久人视频 | 99综合电影在线视频 | 麻豆国产精品va在线观看不卡 | 日韩成人邪恶影片 | 九九交易行官网 | 日韩在线一区二区免费 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 亚洲成人二区 | 青青久草在线视频 | 久久久91精品国产一区二区三区 | 亚洲第一区精品 | 国产高清av在线播放 | 一区二区三区免费在线观看视频 | a级片久久 | 天天综合网入口 | 在线视频欧美日韩 | 日韩精品欧美专区 | 久久艹艹 | 在线观看国产麻豆 | 久久黄色免费视频 | 九九热免费观看 | 三上悠亚一区二区在线观看 | 美女网色| 亚洲男模gay裸体gay | 国产精品99久久久久人中文网介绍 | 婷婷五天天在线视频 | 久久久精品亚洲 | 日韩午夜小视频 | 久久中文网 | 九九热久久免费视频 | 97福利在线观看 | 日日日操 | 99热这里只有精品久久 | 不卡电影免费在线播放一区 | 久久国色夜色精品国产 | 91综合视频在线观看 | 欧美在线18 | 又黄又爽又湿又无遮挡的在线视频 | 精品在线免费观看 | 国产黄影院色大全免费 | 91在线亚洲 | 在线精品视频免费播放 | 成人午夜毛片 | av中文字幕剧情 | 久久精品高清 | 一区二区三区 中文字幕 | 9在线观看免费高清完整版 玖玖爱免费视频 | 深爱开心激情 | 青青看片 | 超碰999| 亚洲在线观看av | 免费在线观看污网站 | 97av视频| 手机av电影在线观看 | 91免费视频国产 | 狠狠干夜夜操天天爽 | 亚洲欧洲精品一区二区精品久久久 | 五月天狠狠操 | 欧美精品一区二区在线播放 | 99久久精品免费看国产麻豆 | 亚洲精品国内 | 国产 欧美 日产久久 | 亚欧洲精品视频在线观看 | 欧美精品一区二区三区四区在线 | 人人干人人草 | 亚洲国产午夜视频 | 在线看片视频 | 亚洲国产午夜视频 | 亚洲一区视频在线播放 | 久久久精品电影 | 国产一区在线免费观看视频 | 日韩91在线 | 99精品在线免费视频 | 日本在线观看一区二区三区 | 在线观看岛国片 | 欧美成人tv | 欧美日韩二区在线 | 国产码电影 | 在线视频 亚洲 | 久久人网 | 久久久久区 | 久久99国产综合精品免费 | 美女网站视频色 | 二区三区在线视频 | 亚洲激情视频 | 一本一本久久a久久精品综合 | 亚洲国产三级在线观看 | 免费看的黄色小视频 | 97在线视频免费观看 | 五月天久久狠狠 | 美女黄频在线观看 | 国产亚洲视频在线观看 | 九九久久久久久久久激情 | 国产中文字幕视频在线观看 | 99久久久成人国产精品 | 天天综合网天天综合色 | 粉嫩一区二区三区粉嫩91 | 亚洲一级片| 天天操狠狠操 | 日韩日韩日韩日韩 | www.777奇米 | 99热国产在线中文 | 亚洲欧美日韩一二三区 | 青青河边草免费观看完整版高清 | 麻豆mv在线观看 | 人人插人人费 | 黄色大全免费网站 | av888.com | 久久99热精品这里久久精品 | 精品国产aⅴ麻豆 | 色综合夜色一区 | 日韩精品在线观看av | 亚洲资源 | 久久国产精品一区二区三区 | 婷婷丁香导航 | 天天干天天综合 | 欧美亚洲一区二区在线 | 日本成人免费在线观看 | 福利在线看片 | 国产精品一区免费在线观看 | 精品一区二区免费 | 天天操天天爱天天干 | 成片视频免费观看 | 奇米影视8888 | 国产午夜视频在线观看 | 99视频| 九九久久国产精品 | 在线观看视频你懂的 | 亚洲国产精品推荐 | 久久久官网 | 69国产精品视频 | 久久公开视频 | 久久综合婷婷国产二区高清 | 欧美色图亚洲图片 | 在线视频免费观看 | 亚洲国产高清视频 | 日韩成人精品一区二区三区 | 亚洲一级黄色片 | 国产99一区二区 | 九九av | 在线播放日韩 | 激情丁香综合五月 | 国产v亚洲v | 人人狠狠综合久久亚洲婷 | 精品视频| 六月丁香综合 | 国产精品丝袜在线 | 国产999精品久久久久久绿帽 | 日韩网站在线观看 | 在线播放日韩av | 99久久久久 | www.福利 | 亚洲精品视频在线观看网站 | 天天玩天天操天天射 | 久久免费观看少妇a级毛片 久久久久成人免费 | 国产中文字幕三区 | 在线观看日韩 | 在线亚洲小视频 | 午夜精品久久久久久久99热影院 | 国产一区二区三精品久久久无广告 | 美女网站视频免费都是黄 | 亚洲男男gⅴgay双龙 | 久久精品国产99国产 | 久草免费在线视频 | 福利视频导航网址 | 一本之道乱码区 | 亚洲婷婷免费 | 国产成人av免费在线观看 | 国产一区网址 | 五月婷婷视频 | 高清中文字幕 | 久久久久久久综合色一本 | 999在线观看视频 | 国产日韩欧美视频 | 免费日韩 精品中文字幕视频在线 | 久久久久欧美精品999 | 69精品久久| 不卡精品 | 亚洲成av人片在线观看香蕉 | 99久久精品国产亚洲 | 国产精品午夜免费福利视频 | 99精品影视 | 精品国产99 | 精品一区精品二区 | 国产一区在线不卡 | www.综合网.com| 天天躁日日躁狠狠躁av中文 | 五月婷婷综合在线观看 | 久久久久欧美精品 | 91av视频在线免费观看 | 狠狠狠狠干 | 欧美精品在线观看免费 | 波多野结衣综合网 | 成人电影毛片 | 99久久精品国产观看 | 亚洲视频www| 日韩欧美在线第一页 | 99热在线国产精品 | 日韩免费一级a毛片在线播放一级 | 久久久免费精品国产一区二区 | 又爽又黄又刺激的视频 | 激情综合五月 | 国产亚洲精品久久久久久 | 在线看片视频 | 国产午夜精品久久久久久久久久 | 精久久久久 | 欧美精品小视频 | 国产偷v国产偷∨精品视频 在线草 | 在线成人看片 | 国产精品成人免费 | 91麻豆精品国产午夜天堂 | 开心激情网五月天 | 欧美综合久久久 | 久久久久久久久久国产精品 | 黄色av一级| av在线播放一区二区三区 | 色噜噜日韩精品一区二区三区视频 | 福利一区二区三区四区 | 欧美午夜视频在线 | 国产亚洲一区 | 免费在线黄色av | 色综合久久综合网 | 鲁一鲁影院 | 91精品啪在线观看国产线免费 | 成人在线播放av | 日韩视频一 | 色视频网站在线观看一=区 a视频免费在线观看 | www.国产在线视频 | 国产高清在线一区 | 91av久久| 天天操操| 久久精品直播 | 国产精品麻豆欧美日韩ww | 亚洲午夜精品一区 | 狠狠狠狠狠狠天天爱 | 五月视频 | 国产福利一区二区在线 | 91片在线观看 | 中文字幕美女免费在线 | 夜夜视频欧洲 | 欧美性极品xxxx做受 | 99精品一区二区三区 | 日本一区二区高清不卡 | 色综合久久精品 | 久久精品高清视频 | av成人免费观看 | 欧美国产一区二区 | 成年人免费在线观看网站 | 91高清一区| 日韩精品91偷拍在线观看 | 国产亚洲精品成人av久久影院 | 久久久久久久久久久久久久电影 | 日韩精品免费在线播放 | 久草视频资源 | 久久久久 | 天天操天天操天天操 | 日韩精品第1页 | 丁香激情五月 | 日韩视频免费观看高清完整版在线 | 97香蕉久久超级碰碰高清版 | 久久久久久久久久网站 | 国产精品一二 | www麻豆视频 | 九九在线国产视频 | 国产精品高潮呻吟久久av无 |