13-面向?qū)ο?
- 1、繼承簡(jiǎn)介
- 繼承是面向?qū)ο笕筇匦灾?/li>
- 通過(guò)繼承我們可以使一個(gè)類獲取到其他類中的屬性和方法
- 在定義類時(shí),可以在類名后面的括號(hào)中指定當(dāng)前類的父類(超類、基類)
- 繼承提高了類的復(fù)用性。讓類與類之間產(chǎn)生了關(guān)系。有了這個(gè)關(guān)系,才有了多態(tài)的特性
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/17 0017 21:02
# @Author : Oliver
#繼承是面向?qū)ο蟮娜筇匦灾?# 通過(guò)繼承我們可以使一個(gè)類獲取其他類的屬性和方法
# class Person():
# name=''
# age=''
# class Doctor():
# name=''
# age=''
#
# def heal(self):
# print('治病救人!')
#
# class Student():
# name=''
# age=''
#
# def study(self):
# print('好好學(xué)習(xí),天天向上?。?!')
#
# object是所有類的父類
# issubclass()檢查一個(gè)類是不是另一個(gè)類的子類
class Animal(object):
def run(self):
print('動(dòng)物跑起來(lái)了.....')
def sleep(self):
print('動(dòng)物睡覺(jué)...')
a=Animal()
# a.run()
# 需求:定義一個(gè)狗類
# 1.直接修改Animal這個(gè)類,在這個(gè)類中添加我們需要的功能
# 這種方式比較麻煩,并且會(huì)違反OCP原則
# 顯然這個(gè)方式不推薦
# 2.直接創(chuàng)建一個(gè)新的類
# 創(chuàng)建一個(gè)新類是比較麻煩的,并且需要大量的賦值粘貼,會(huì)出現(xiàn)大量的重復(fù)代碼
# class Dog():
# def run(self):
# print('狗跑起來(lái)了.....')
# def sleep(self):
# print('狗睡覺(jué)...')
# def speak(self):
# print('汪汪汪!')
#
# 3.直接從Animal類中繼承他的屬性和方法
# 在定義類的時(shí)候,可以在類名的后面加上一個(gè)括號(hào),這個(gè)括號(hào)中可以指定當(dāng)前類的父類(超類、基類)
class Dog(Animal):
def speak(self):
print('汪汪汪!')
def run(self):
print('狗再跑?。?)#更新了狗的方法
d=Dog()
# Dog中沒(méi)有sleep的方法,但是父類有,很明顯d可以調(diào)用,這就是Dog繼承了Animal這個(gè)父類的方法和屬性
d.run()
d.sleep()
d.speak()
#判斷d是不是Dog的實(shí)例
r=isinstance(d,Dog)
print(r)#最后發(fā)現(xiàn)是的
#判斷d是不是Animal的實(shí)例
r=isinstance(d,Animal)
print(r)#最后發(fā)現(xiàn)是的
# 也就是d也是父類的實(shí)例
print()
print(issubclass(Dog,Animal))
print(issubclass(Animal,object))
結(jié)果顯示:
狗再跑!!
動(dòng)物睡覺(jué)...
汪汪汪!
True
True
True
True
Process finished with exit code 0
- 2、方法重寫
- 如果在子類中有和父類同名的方法,則通過(guò)子類實(shí)例去調(diào)用方法時(shí),會(huì)調(diào)用子類的方法而不是父類的方法,這個(gè)特點(diǎn)我們稱之為方法的重寫(覆蓋)
- 當(dāng)我們調(diào)用一個(gè)對(duì)象的方法時(shí):
- 會(huì)優(yōu)先去當(dāng)前對(duì)象中尋找是否具有該方法,如果有則直接調(diào)用
- 如果沒(méi)有,則去當(dāng)前對(duì)象的父類中尋找,如果父類中有則直接調(diào)用父類中的方法
- 如果沒(méi)有,則去父類中的父類尋找,以此類推,直到找到object,如果依然沒(méi)有找到就報(bào)錯(cuò)了
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/17 0017 21:27
# @Author : Oliver
# 重寫/覆蓋(override)
class A(object):
def test(self):
print('A....')
class B(A):
def test(self):
print('B....')
class C(B):
pass
c=C()
c.test()
結(jié)果顯示:
B....
Process finished with exit code 0
- 3、super()
- super()可以獲取當(dāng)前類的父類
- 并且通過(guò)super()返回對(duì)象調(diào)用父類方法時(shí),不需要傳遞self
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/17 0017 21:37
# @Author : Oliver
# 父類中所有的方法都會(huì)被子類繼承,包括特殊的方法
class Animal(object):
def __init__(self,name,sex):
self._name=name
self._sex=sex
@property
def sex(self):
return self._sex
@sex.setter
def sex(self, sex):
self._sex = sex
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name=name
def run(self):
print('動(dòng)物跑起來(lái)了.....')
def sleep(self):
print('動(dòng)物睡覺(jué)...')
class Dog(Animal):
def __init__(self,name,age,sex):
# self._name=name
# self._age=age
# self._sex=sex
# Animal.__init__(self,name,sex)
super().__init__(name,sex)
@property
def age(self):
return self._age
@age.setter
def age(self,age):
self._age = age
def speak(self):
print('汪汪汪?。?!')
def run(self):
print('狗在跑.....')
d=Dog('試試',4,'男')
print(d.name)
print(d.sex)
# super()可以獲取當(dāng)前類的父類
- 4、多重繼承
- 在Python中是支持多重繼承的。也就是我們可以為一個(gè)類同時(shí)制定多個(gè)父類
- 可以在類名的()后邊添加多個(gè)類,來(lái)實(shí)現(xiàn)多重繼承
- 多重繼承,會(huì)使子類同時(shí)擁有多個(gè)父類,并且會(huì)獲取到所有父類中的方法
- 在開(kāi)發(fā)中沒(méi)有特殊情況,應(yīng)該盡量避免使用多重繼承。因?yàn)槎嘀乩^承會(huì)讓我們的代碼更加復(fù)雜
- 如果多個(gè)父類中有同名的方法,則會(huì)先在第一個(gè)父類中尋找,如果該父類還有父類,則在該父類的父類中查找,沒(méi)有的話,然后找第二個(gè),找第三個(gè)...前面會(huì)覆蓋后面的
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/18 0018 12:34
# @Author : Oliver
# 類名.__bases__這個(gè)屬性可以用來(lái)獲取當(dāng)前類的父類
class A(object):
def test(self):
print('A....')
class B(object):
def test(self):
print('B....')
# 可以在類名的()后邊添加多個(gè)類,來(lái)實(shí)現(xiàn)多重繼承
class C(A,B):
pass
c=C()
print(C.__bases__)
# (<class '__main__.B'>,)元組還有逗號(hào),說(shuō)明可以有多個(gè)父類
print(B.__bases__)
c.test()
# 多個(gè)父類中有同名的方法,則會(huì)先在第一個(gè)父類中尋找,然后找第二個(gè),找第三個(gè)...前面會(huì)覆蓋后面的
結(jié)果顯示:
(<class '__main__.A'>, <class '__main__.B'>)
(<class 'object'>,)
A....
Process finished with exit code 0
- 5、多態(tài)
- 多態(tài)是面向?qū)ο蟮娜筇匦灾?。從字面理解就是多種形態(tài)
- 一個(gè)對(duì)象可以以不同形態(tài)去呈現(xiàn)
- 面向?qū)ο笕筇匦?
- 封裝 確保對(duì)象中數(shù)據(jù)的安全
- 基礎(chǔ) 保證了對(duì)象的擴(kuò)展性
- 多態(tài) 保證了程序的靈活性
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/18 0018 12:50
# @Author : Oliver
# 多態(tài)也是面向?qū)ο蟮娜筇匦灾?# 一個(gè)對(duì)象可以以不同的形態(tài)去呈現(xiàn)
class A:
def __init__(self,name):
self._name=name
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name=name
class B:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
class C:
pass
a=A('張三')
b=B('李四')
c=C()
# 定義一個(gè)函數(shù) 這種形式就是多態(tài)
def speak(obj):
print('你好%s'%obj.name)
# 只要對(duì)象有name就可以,不用對(duì)象是A,還是B
# 適應(yīng)性更高
speak(a)
# speak(c)
# 這種形式就違反了一個(gè)多態(tài)的原則
def speak2(obj):
# 類型檢查
if isinstance(obj,A):#只能處理一類對(duì)象
print('你好%s'%obj.name)
speak2(a)
# 舉個(gè)例子好理解
lst=[1,2,3]
print(len(lst))
s='python'
print(len(s))
# len()可以處理不同對(duì)象,就相當(dāng)于上述的speak()
# 這就是一個(gè)多態(tài)
# 列表字符串都封裝了__len__,這是他們的共同點(diǎn)
- 6、屬性和方法
- 屬性
- 類屬性,直接在類中定義的屬性是類屬性
- 類屬性可以通過(guò)類或類的實(shí)例訪問(wèn)到。但是類屬性只能通過(guò)類對(duì)象來(lái)修改,無(wú)法通過(guò)實(shí)例對(duì)象修改
- 實(shí)例屬性 通過(guò)實(shí)例對(duì)象添加的屬性屬于實(shí)例屬性
- 實(shí)例屬性只能通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn)和修改,類對(duì)象無(wú)法訪問(wèn)修改
- 方法
- 在類中定義,以self為第一個(gè)參數(shù)的方法都是實(shí)例方法
- 實(shí)例方法在調(diào)用時(shí),Python會(huì)將調(diào)用對(duì)象以self傳入
- 實(shí)例方法可以通過(guò)類實(shí)例和類去調(diào)用
- 當(dāng)通過(guò)實(shí)例調(diào)用時(shí),會(huì)自動(dòng)將當(dāng)前調(diào)用對(duì)象作為self傳入
- 當(dāng)通過(guò)類調(diào)用時(shí),不會(huì)自動(dòng)傳遞self,我們必須手動(dòng)傳遞self
- 類方法 在類的內(nèi)容以@classmethod 來(lái)修飾的方法屬性類方法
- 類方法第一個(gè)參數(shù)是cls 也會(huì)自動(dòng)被傳遞。cls就是當(dāng)前的類對(duì)象
- 類方法和實(shí)例方法的區(qū)別,實(shí)例方法的第一個(gè)參數(shù)是self,類方法的第一個(gè)參數(shù)是cls
- 類方法可以通過(guò)類去調(diào)用,也可以通過(guò)實(shí)例調(diào)用
- 靜態(tài)方法
- 在類中用@staticmethod來(lái)修飾的方法屬于靜態(tài)方法
- 靜態(tài)方法不需要指定任何的默認(rèn)參數(shù),靜態(tài)方法可以通過(guò)類和實(shí)例調(diào)用
- 靜態(tài)方法,基本上是一個(gè)和當(dāng)前類無(wú)關(guān)的方法,它只是一個(gè)保存到當(dāng)前類中的函數(shù)
- 靜態(tài)方法一般都是些工具方法,和當(dāng)前類無(wú)關(guān)
- 屬性
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/18 0018 13:24
# @Author : Oliver
class A:
# 類屬性:直接在類中定義的屬性就是類屬性
# 類屬性可以通過(guò)類對(duì)象和實(shí)例對(duì)象來(lái)訪問(wèn)
# 類屬性只能通過(guò)類對(duì)象來(lái)修改,不能通過(guò)實(shí)例對(duì)象來(lái)修改
count=0
def __init__(self):
self.name='張三'
# 這其實(shí)是一個(gè)實(shí)例屬性,因?yàn)閟elf就是a,通過(guò)self將這個(gè)屬性添加到了當(dāng)前的實(shí)例對(duì)象中
# 這是實(shí)例方法
def test(self):
print('這是個(gè)test方法!?。?)
# 類方法
#在類的內(nèi)部使用@classmethod修飾的方式屬于類方法
# 類方法的第一個(gè)參數(shù)cls,也會(huì)自動(dòng)傳遞,cls表示的就是當(dāng)前的類對(duì)象
@classmethod
def test2(cls):
print('這是個(gè)test2方法?。?!')
print(cls.count)
# 靜態(tài)方法
# 在類中被@staticmethod來(lái)修飾的方法屬于靜態(tài)方法
@staticmethod
def test3(self):
print('這是個(gè)test3方法?。?!')
a=A()
# 實(shí)例屬性:通過(guò)實(shí)例對(duì)象添加的屬性是實(shí)例屬性
# a.count=10
# A.count=10
# print('A',A.count)
# print('a',a.count)
#
# print('a',a.name)
# print('A',A.name)這個(gè)是會(huì)報(bào)錯(cuò)的
# 實(shí)例屬性只能通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn)、修改,類對(duì)象無(wú)法訪問(wèn)修改
a.test()
A.test(a)
# a.test()等價(jià)于A.test(a)
A.test2()
a.test2()
# A.test2()等價(jià)于a.test2()
A.test3()
a.test3()
結(jié)果顯示:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/9/18 0018 13:24
# @Author : Oliver
class A:
# 類屬性:直接在類中定義的屬性就是類屬性
# 類屬性可以通過(guò)類對(duì)象和實(shí)例對(duì)象來(lái)訪問(wèn)
# 類屬性只能通過(guò)類對(duì)象來(lái)修改,不能通過(guò)實(shí)例對(duì)象來(lái)修改
count=0
def __init__(self):
self.name='張三'
# 這其實(shí)是一個(gè)實(shí)例屬性,因?yàn)閟elf就是a,通過(guò)self將這個(gè)屬性添加到了當(dāng)前的實(shí)例對(duì)象中
# 這是實(shí)例方法
def test(self):
print('這是個(gè)test方法?。?!')
# 類方法
#在類的內(nèi)部使用@classmethod修飾的方式屬于類方法
# 類方法的第一個(gè)參數(shù)cls,也會(huì)自動(dòng)傳遞,cls表示的就是當(dāng)前的類對(duì)象
@classmethod
def test2(cls):
print('這是個(gè)test2方法!?。?)
print(cls.count)
# 靜態(tài)方法
# 在類中被@staticmethod來(lái)修飾的方法屬于靜態(tài)方法
@staticmethod
def test3(self):
print('這是個(gè)test3方法?。。?)
a=A()
# 實(shí)例屬性:通過(guò)實(shí)例對(duì)象添加的屬性是實(shí)例屬性
# a.count=10
# A.count=10
# print('A',A.count)
# print('a',a.count)
#
# print('a',a.name)
# print('A',A.name)這個(gè)是會(huì)報(bào)錯(cuò)的
# 實(shí)例屬性只能通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn)、修改,類對(duì)象無(wú)法訪問(wèn)修改
a.test()
A.test(a)
# a.test()等價(jià)于A.test(a)
A.test2()
a.test2()
# A.test2()等價(jià)于a.test2()
A.test3()
a.test3()