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

語法格式
Python 支持多重繼承,一個子類可以繼承多個父類。繼承的語法格式如下:
class 子類類名(父類 1[,父類 2,…]):
類體
如果在類定義中沒有指定父類,則默認(rèn)父類是 object 類。也就是說,object 是所有類的父 類,里面定義了一些所有類共有的默認(rèn)實現(xiàn),比如:new()。
定義子類時,必須在其構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)。調(diào)用格式如下:
父類名.init(self, 參數(shù)列表)
# 測試?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) #繼承于父類的私有屬性的訪問
輸出:
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)造方法之外的所有成員,包括方法,屬性,私有方法,私有屬性,只不過私有方法和屬性不能直接訪問。
2.方法重寫:子類可以重新定義父類中的方法,這樣就會覆蓋父類的方法,也稱為“重寫”
# 重寫父類方法的測試
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)
通過類的方法 mro()或者類的屬性__mro__可以輸出這個類的繼承層次結(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()查看對象屬性
# 測試?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 有一個__str__()方法,用于返回一個對于“對象的描述”,對應(yīng)于內(nèi)置函數(shù) str()。經(jīng)常用于 print()方法,幫助我們查看對象的信息。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 支持多重繼承,一個子類可以有多個“直接父類”。這樣,就具備了“多個父 類”的特點。但是由于,這樣會被“類的整體層次”搞的異常復(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 支持多繼承,如果父類中有相同名字的方法,在子類沒有指定父類名時,解釋器將 “從左向右”按順序搜索。
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()獲得父類定義
在子類中,如果想要獲得父類的方法時,我們可以通過 super()來做。super()獲得父類的定義(不是獲得父類的對象)。
# 測試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)是指同一個方法調(diào)用由于對象不同可能會產(chǎn)生不同的行為。
關(guān)于多態(tài)要注意以下 2 點:
1.多態(tài)是方法的多態(tài),屬性沒有多態(tài)。
2.多態(tài)的存在有 2 個必要條件:繼承、方法重寫。
# 多態(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
特殊方法和重載運算符
python重的運算符實際上是通過調(diào)用對象的特殊方法實現(xiàn)的。
a = 20 b = 30 print(a+b) print(a.__add__(b)) 輸出: 50 50
常見的特殊方法:

每個運算符實際上都對應(yīng)了相應(yīng)的方法:


# 測試運算符重載
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é)束的屬性,這些是特殊屬性,有特殊用法。這里列出常見的特殊屬性:

#測試特殊屬性
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對象的屬性列表
print(c.__class__) #c對象的類
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>
對象的淺拷貝和深拷貝
- 變量的賦值操作
只是形成兩個變量,實際還是指向同一個對象。
- 淺拷貝Python
拷貝一般都是淺拷貝??截悤r,對象包含的子對象內(nèi)容不拷貝。因此,源對象 和拷貝對象會引用同一個子對象。
- ·深拷貝使用
使用copy 模塊的 deepcopy 函數(shù),遞歸拷貝對象中包含的子對象。源對象和拷貝對象 所有的子對象也不同。
# 測試淺拷貝和深拷貝
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('測試賦值----')
m0 = m1
print('m1:\t',m1)
m1.cpu.caculate()
m1.screen.show()
print('m0:\t',m0)
m0.cpu.caculate()
m0.screen.show()
print('測試淺復(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('測試深復(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()
輸出:
測試賦值----
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>
測試淺復(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>
測試深復(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)系,我們可以使用“繼承”。從而實現(xiàn)子類擁有的父類的方法和屬性。“is-a” 關(guān)系指的是類似這樣的關(guān)系:狗是動物,dog is animal。狗類就應(yīng)該繼承動物類。
“has-a”關(guān)系,我們可以使用“組合”,也能實現(xiàn)一個類擁有另一個類的方法和屬性。” has-a”關(guān)系指的是這樣的關(guān)系:手機擁有 CPU。 MobilePhone has a CPU。
設(shè)計模式_工廠模式實現(xiàn)
設(shè)計模式是面向?qū)ο笳Z言特有的內(nèi)容,是我們在面臨某一類問題時候固定的做法,設(shè)計 模式有很多種,比較流行的是:GOF(Goup Of Four)23 種設(shè)計模式。當(dāng)然,我們沒有 必要全部學(xué)習(xí),學(xué)習(xí)幾個常用的即可。
對于初學(xué)者,我們學(xué)習(xí)兩個最常用的模式:工廠模式和單例模式。
工廠模式實現(xiàn)了創(chuàng)建者和調(diào)用者的分離,使用專門的工廠類將選擇實現(xiàn)類、創(chuàng)建對象進(jìn)行統(tǒng)一的管理和控制。
#測試工廠模式
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è)計模式_單例模式實現(xiàn)
單例模式(Singleton Pattern)的核心作用是確保一個類只有一個實例,并且提供一個訪問該實例的全局訪問點。
單例模式只生成一個實例對象,減少了對系統(tǒng)資源的開銷。當(dāng)一個對象的產(chǎn)生需要比較 多的資源,如讀取配置文件、產(chǎn)生其他依賴對象時,可以產(chǎn)生一個“單例對象”,然后永久 駐留內(nèi)存中,從而極大的降低開銷。
# 測試單例模式
class MySingleton():
__obj = None
__init_flag = True
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls) # __obj對象只創(chuàng)建一次 obj對象就是Mysingleton對象
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
工廠模式和單例模式的整合使用
# 測試工廠模式和單例模式的混合使用
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é)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
linux系統(tǒng)使用python獲取內(nèi)存使用信息腳本分享
這篇文章主要介紹了linux系統(tǒng)使用python獲取內(nèi)存使用情況信息,大家參考使用吧2014-01-01
解決Python print 輸出文本顯示 gbk 編碼錯誤問題
這篇文章主要介紹了解決Python print 輸出文本顯示 gbk 編碼錯誤問題,本文給出了三種解決方法,需要的朋友可以參考下2018-07-07
Python光學(xué)仿真wxpython透鏡演示系統(tǒng)計算與繪圖
這篇文章主要為大家介紹了Python光學(xué)仿真wxpython透鏡演示系統(tǒng)計算與繪圖的實現(xiàn)示例。有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
使用Pytorch Geometric進(jìn)行鏈接預(yù)測的實現(xiàn)代碼
PyTorch Geometric (PyG)是構(gòu)建圖神經(jīng)網(wǎng)絡(luò)模型和實驗各種圖卷積的主要工具,在本文中我們將通過鏈接預(yù)測來對其進(jìn)行介紹,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-10-10
PyQt5實現(xiàn)數(shù)據(jù)的增刪改查功能詳解
這篇文章主要為大家介紹了如何使用Python中的PyQt5模塊來實現(xiàn)數(shù)據(jù)的增、刪、改、查功能,文中示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-03-03

