Python基礎(chǔ)之面向?qū)ο筮M(jìn)階詳解
面向?qū)ο笕筇卣鹘榻B
封裝(隱藏):隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),知對(duì)外提供必要的方法。
繼承:讓子類擁有父類特征,提高了代碼的重用性。從設(shè)計(jì)上是一種增量進(jìn)化,原有父類設(shè)計(jì)不變的情況下,可以增加新的功能,或者改進(jìn) 已有的算法。
多態(tài):一個(gè)方法調(diào)用由于對(duì)象不同會(huì)產(chǎn)生不同的行為。
繼承
繼承是代碼復(fù)用的一個(gè)非常重要的手段,已有的類,我們稱為“父類或者基類”,新的類,我們稱為“子類或者派生類”。

語(yǔ)法格式
Python 支持多重繼承,一個(gè)子類可以繼承多個(gè)父類。繼承的語(yǔ)法格式如下:
class 子類類名(父類 1[,父類 2,…]):
類體
如果在類定義中沒有指定父類,則默認(rèn)父類是 object 類。也就是說(shuō),object 是所有類的父 類,里面定義了一些所有類共有的默認(rèn)實(shí)現(xiàn),比如:new()。
定義子類時(shí),必須在其構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)。調(diào)用格式如下:
父類名.init(self, 參數(shù)列表)
# 測(cè)試?yán)^承的基本使用
class Person():
def __init__(self, name, age):
self.name = name
self.__age = age #私有屬性
def print_name(self):
print(self.name)
class Student(Person):
def __init__(self, name, age, id):
Person.__init__(self, name, age)
self.id = id
stu = Student('sherry',24,'2017')
stu.print_name()
print(Student.mro()) #查看類的繼承層次結(jié)構(gòu)
print(dir(stu)) # 打印所有方法和屬性
print(stu._Person__age) #繼承于父類的私有屬性的訪問(wèn)
輸出:
sherry
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'id', 'name', 'print_name']
24
1.類成員的繼承和重寫 成員繼承:子類繼承了父類除構(gòu)造方法之外的所有成員,包括方法,屬性,私有方法,私有屬性,只不過(guò)私有方法和屬性不能直接訪問(wèn)。
2.方法重寫:子類可以重新定義父類中的方法,這樣就會(huì)覆蓋父類的方法,也稱為“重寫”
# 重寫父類方法的測(cè)試
class Person():
def __init__(self, name, age):
self.name = name
self.__age = age #私有屬性
def print_name(self):
print(self.name)
class Student(Person):
def __init__(self, name, age, id):
Person.__init__(self, name, age)
self.id = id
def print_name(self):
'''重寫了父類的方法'''
print('my name is ', self.name)
stu = Student('sherry',24,'2017')
stu.print_name()
輸出:
my name is sherry
查看類的繼承層次結(jié)構(gòu)
通過(guò)類的方法 mro()或者類的屬性__mro__可以輸出這個(gè)類的繼承層次結(jié)構(gòu)。
class Person():
def __init__(self, name, age):
self.name = name
self.__age = age #私有屬性
def print_name(self):
print(self.name)
class Student(Person):
def __init__(self, name, age, id):
Person.__init__(self, name, age)
self.id = id
def print_name(self):
'''重寫了父類的方法'''
print('my name is ', self.name)
# stu = Student('sherry',24,'2017')
print(Student.mro())
輸出:
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
object根類
object 類是所有類的父類,因此所有的類都有 object 類的屬性和方法。
dir()查看對(duì)象屬性
# 測(cè)試?yán)^承的基本使用
class Person():
def __init__(self, name, age):
self.name = name
self.__age = age #私有屬性
def print_name(self):
print(self.name)
class Student(Person):
def __init__(self, name, age, id):
Person.__init__(self, name, age)
self.id = id
def print_name(self):
'''重寫了父類的方法'''
print('my name is ', self.name)
obj = object()
stu = Student('sherry',24,'2017')
print(dir(obj))
print(dir(stu))
輸出:
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'id', 'name', 'print_name']
str()方法的重寫
object 有一個(gè)__str__()方法,用于返回一個(gè)對(duì)于“對(duì)象的描述”,對(duì)應(yīng)于內(nèi)置函數(shù) str()。經(jīng)常用于 print()方法,幫助我們查看對(duì)象的信息。str()可以重寫。
class Person():
def __init__(self, name, age):
self.name = name
self.__age = age #私有屬性
def print_name(self):
print(self.name)
def __str__(self):
return 'name:{0} age:{1}'.format(self.name, self.__age)
p = Person('sherry', 24)
print(p)
輸出:
name:sherry age:24
多重繼承
Python 支持多重繼承,一個(gè)子類可以有多個(gè)“直接父類”。這樣,就具備了“多個(gè)父 類”的特點(diǎn)。但是由于,這樣會(huì)被“類的整體層次”搞的異常復(fù)雜,盡量避免使用。(java不支持多重繼承)

class A():
pass
class B():
pass
class C(A,B):
pass
print(C.mro())
輸出:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
MRO()
Python 支持多繼承,如果父類中有相同名字的方法,在子類沒有指定父類名時(shí),解釋器將 “從左向右”按順序搜索。
class A():
pass
class B():
pass
class C(A,B):
pass
print(C.mro())
輸出:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
super()獲得父類定義
在子類中,如果想要獲得父類的方法時(shí),我們可以通過(guò) super()來(lái)做。super()獲得父類的定義(不是獲得父類的對(duì)象)。
# 測(cè)試super()
class A():
def say(self):
print('aa')
class B(A):
def say(self):
super().say() #調(diào)用父類方法
A.say(self) #調(diào)用父類方法
print('bb')
b = B()
b.say()
輸出:
aa
aa
bb
多態(tài)
多態(tài)(polymorphism)是指同一個(gè)方法調(diào)用由于對(duì)象不同可能會(huì)產(chǎn)生不同的行為。
關(guān)于多態(tài)要注意以下 2 點(diǎn):
1.多態(tài)是方法的多態(tài),屬性沒有多態(tài)。
2.多態(tài)的存在有 2 個(gè)必要條件:繼承、方法重寫。
# 多態(tài)
class Man():
def eat(self):
print('eat!')
class Chinese(Man):
def eat(self):
print('eat with chopsticks')
class English(Man):
def eat(self):
print('eat with fork')
class Indian(Man):
def eat(self):
print('eat with hand')
def manEat(m):
if isinstance(m,Man):
m.eat()
else:
print('can not eat!')
manEat(Man())
manEat(Chinese())
manEat(English())
manEat(Indian())
輸出:
eat!
eat with chopsticks
eat with fork
eat with hand
特殊方法和重載運(yùn)算符
python重的運(yùn)算符實(shí)際上是通過(guò)調(diào)用對(duì)象的特殊方法實(shí)現(xiàn)的。
a = 20 b = 30 print(a+b) print(a.__add__(b)) 輸出: 50 50
常見的特殊方法:

每個(gè)運(yùn)算符實(shí)際上都對(duì)應(yīng)了相應(yīng)的方法:


# 測(cè)試運(yùn)算符重載
class Person():
def __init__(self, name):
self.name = name
def __add__(self, other):
if isinstance(other, Person):
return '{0}-{1}'.format(self.name, other.name)
def __mul__(self, other):
if isinstance(other, int):
return self.name * other
p1 = Person('Sherry')
p2 = Person('Lily')
print(p1 + p2)
print(p1*10)
輸出:
Sherry-Lily
SherrySherrySherrySherrySherrySherrySherrySherrySherrySherry
特殊屬性
python中包含了很多雙下劃線開始和結(jié)束的屬性,這些是特殊屬性,有特殊用法。這里列出常見的特殊屬性:

#測(cè)試特殊屬性
class A():
def say(self):
print('aa')
class B():
def say(self):
print('bb')
class C(B,A):
def __init__(self,name):
super().__init__()
self.name = name
c = C('sherry')
print(c.__dict__) #c對(duì)象的屬性列表
print(c.__class__) #c對(duì)象的類
print(C.__bases__) #C類的基類
print(C.__mro__) #C類的繼承關(guān)系
print(C.__subclasses__)#C類的子類
輸出:
{'name': 'sherry'}
<class '__main__.C'>
(<class '__main__.B'>, <class '__main__.A'>)
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
<built-in method __subclasses__ of type object at 0x7fefdacc8dd0>
對(duì)象的淺拷貝和深拷貝
- 變量的賦值操作
只是形成兩個(gè)變量,實(shí)際還是指向同一個(gè)對(duì)象。
- 淺拷貝Python
拷貝一般都是淺拷貝??截悤r(shí),對(duì)象包含的子對(duì)象內(nèi)容不拷貝。因此,源對(duì)象 和拷貝對(duì)象會(huì)引用同一個(gè)子對(duì)象。
- ·深拷貝使用
使用copy 模塊的 deepcopy 函數(shù),遞歸拷貝對(duì)象中包含的子對(duì)象。源對(duì)象和拷貝對(duì)象 所有的子對(duì)象也不同。
# 測(cè)試淺拷貝和深拷貝
import copy
class MobilePhone():
def __init__(self, cpu, screen):
self.cpu = cpu
self.screen = screen
class CPU():
def caculate(self):
print('cpu:\t', self)
class Screen():
def show(self):
print('screen:\t',self)
m1 = MobilePhone(CPU(), Screen())
print('測(cè)試賦值----')
m0 = m1
print('m1:\t',m1)
m1.cpu.caculate()
m1.screen.show()
print('m0:\t',m0)
m0.cpu.caculate()
m0.screen.show()
print('測(cè)試淺復(fù)制----')
m2 = copy.copy(m1)
print('m1:\t',m1)
m1.cpu.caculate()
m1.screen.show()
print('m2:\t',m2)
m2.cpu.caculate()
m2.screen.show()
print('測(cè)試深復(fù)制----')
m3 = copy.deepcopy(m1)
print('m1:\t',m1)
m1.cpu.caculate()
m1.screen.show()
print('m3:\t',m3)
m3.cpu.caculate()
m3.screen.show()
輸出:
測(cè)試賦值----
m1: <__main__.MobilePhone object at 0x7f8b0d6ed190>
cpu: <__main__.CPU object at 0x7f8b0d6ed130>
screen: <__main__.Screen object at 0x7f8b0d6ed100>
m0: <__main__.MobilePhone object at 0x7f8b0d6ed190>
cpu: <__main__.CPU object at 0x7f8b0d6ed130>
screen: <__main__.Screen object at 0x7f8b0d6ed100>
測(cè)試淺復(fù)制----
m1: <__main__.MobilePhone object at 0x7f8b0d6ed190>
cpu: <__main__.CPU object at 0x7f8b0d6ed130>
screen: <__main__.Screen object at 0x7f8b0d6ed100>
m2: <__main__.MobilePhone object at 0x7f8b0d6a9940>
cpu: <__main__.CPU object at 0x7f8b0d6ed130>
screen: <__main__.Screen object at 0x7f8b0d6ed100>
測(cè)試深復(fù)制----
m1: <__main__.MobilePhone object at 0x7f8b0d6ed190>
cpu: <__main__.CPU object at 0x7f8b0d6ed130>
screen: <__main__.Screen object at 0x7f8b0d6ed100>
m3: <__main__.MobilePhone object at 0x7f8b0d6ed280>
cpu: <__main__.CPU object at 0x7f8b0d6ede20>
screen: <__main__.Screen object at 0x7f8b0d6edd30>
組合
“is-a”關(guān)系,我們可以使用“繼承”。從而實(shí)現(xiàn)子類擁有的父類的方法和屬性。“is-a” 關(guān)系指的是類似這樣的關(guān)系:狗是動(dòng)物,dog is animal。狗類就應(yīng)該繼承動(dòng)物類。
“has-a”關(guān)系,我們可以使用“組合”,也能實(shí)現(xiàn)一個(gè)類擁有另一個(gè)類的方法和屬性。” has-a”關(guān)系指的是這樣的關(guān)系:手機(jī)擁有 CPU。 MobilePhone has a CPU。
設(shè)計(jì)模式_工廠模式實(shí)現(xiàn)
設(shè)計(jì)模式是面向?qū)ο笳Z(yǔ)言特有的內(nèi)容,是我們?cè)诿媾R某一類問(wèn)題時(shí)候固定的做法,設(shè)計(jì) 模式有很多種,比較流行的是:GOF(Goup Of Four)23 種設(shè)計(jì)模式。當(dāng)然,我們沒有 必要全部學(xué)習(xí),學(xué)習(xí)幾個(gè)常用的即可。
對(duì)于初學(xué)者,我們學(xué)習(xí)兩個(gè)最常用的模式:工廠模式和單例模式。
工廠模式實(shí)現(xiàn)了創(chuàng)建者和調(diào)用者的分離,使用專門的工廠類將選擇實(shí)現(xiàn)類、創(chuàng)建對(duì)象進(jìn)行統(tǒng)一的管理和控制。
#測(cè)試工廠模式
class CarFactory():
def creatCar(self, brand):
if brand == '奔馳':
return Benz()
elif brand == '寶馬':
return BMW()
elif brand == '比亞迪':
return BYD()
else:
print('can not create!')
class Benz():
pass
class BMW():
pass
class BYD():
pass
factory = CarFactory()
c1 = factory.creatCar('奔馳')
c2 = factory.creatCar('寶馬')
c3 = factory.creatCar('比亞迪')
設(shè)計(jì)模式_單例模式實(shí)現(xiàn)
單例模式(Singleton Pattern)的核心作用是確保一個(gè)類只有一個(gè)實(shí)例,并且提供一個(gè)訪問(wèn)該實(shí)例的全局訪問(wèn)點(diǎn)。
單例模式只生成一個(gè)實(shí)例對(duì)象,減少了對(duì)系統(tǒng)資源的開銷。當(dāng)一個(gè)對(duì)象的產(chǎn)生需要比較 多的資源,如讀取配置文件、產(chǎn)生其他依賴對(duì)象時(shí),可以產(chǎn)生一個(gè)“單例對(duì)象”,然后永久 駐留內(nèi)存中,從而極大的降低開銷。
# 測(cè)試單例模式
class MySingleton():
__obj = None
__init_flag = True
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls) # __obj對(duì)象只創(chuàng)建一次 obj對(duì)象就是Mysingleton對(duì)象
return cls.__obj
def __init__(self, name):
if self.__init_flag == True:
print('init....')
self.name = name
self.__init_flag = False
a = MySingleton('aa')
b = MySingleton('bb')
c = MySingleton('cc')
print(a)
print(a.name)
print(b)
print(b.name)
print(c)
print(c.name)
輸出:
init....
<__main__.MySingleton object at 0x7fce0f6e8130>
aa
<__main__.MySingleton object at 0x7fce0f6e8130>
aa
<__main__.MySingleton object at 0x7fce0f6e8130>
aa
工廠模式和單例模式的整合使用
# 測(cè)試工廠模式和單例模式的混合使用
class CarFactory():
__obj = None
__init_flag = True
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls)
return cls.__obj
def __init__(self):
if self.__init_flag:
print('init factory')
self.__init_flag = False
def creatCar(self, brand):
if brand == '奔馳':
return Benz()
elif brand == '寶馬':
return BMW()
elif brand == '比亞迪':
return BYD()
else:
print('can not create!')
class Benz():
pass
class BMW():
pass
class BYD():
pass
factory = CarFactory()
c1 = factory.creatCar('奔馳')
c2 = factory.creatCar('寶馬')
c3 = factory.creatCar('比亞迪')
factory2 = CarFactory()
print(factory)
print(factory2)
輸出:
init factory
<__main__.CarFactory object at 0x7fd286eecc10>
<__main__.CarFactory object at 0x7fd286eecc10>
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
插入排序_Python與PHP的實(shí)現(xiàn)版(推薦)
下面小編就為大家?guī)?lái)一篇插入排序_Python與PHP的實(shí)現(xiàn)版(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
linux系統(tǒng)使用python獲取內(nèi)存使用信息腳本分享
這篇文章主要介紹了linux系統(tǒng)使用python獲取內(nèi)存使用情況信息,大家參考使用吧2014-01-01
解決Python print 輸出文本顯示 gbk 編碼錯(cuò)誤問(wèn)題
這篇文章主要介紹了解決Python print 輸出文本顯示 gbk 編碼錯(cuò)誤問(wèn)題,本文給出了三種解決方法,需要的朋友可以參考下2018-07-07
Python光學(xué)仿真wxpython透鏡演示系統(tǒng)計(jì)算與繪圖
這篇文章主要為大家介紹了Python光學(xué)仿真wxpython透鏡演示系統(tǒng)計(jì)算與繪圖的實(shí)現(xiàn)示例。有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
使用Pytorch Geometric進(jìn)行鏈接預(yù)測(cè)的實(shí)現(xiàn)代碼
PyTorch Geometric (PyG)是構(gòu)建圖神經(jīng)網(wǎng)絡(luò)模型和實(shí)驗(yàn)各種圖卷積的主要工具,在本文中我們將通過(guò)鏈接預(yù)測(cè)來(lái)對(duì)其進(jìn)行介紹,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-10-10
PyQt5實(shí)現(xiàn)數(shù)據(jù)的增刪改查功能詳解
這篇文章主要為大家介紹了如何使用Python中的PyQt5模塊來(lái)實(shí)現(xiàn)數(shù)據(jù)的增、刪、改、查功能,文中示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-03-03

