python中面向对象的缺点_python中的面向对象和面向过程
一、面向對象和面向過程
一、什么是面向過程
核心是過程二字:面向過程是一種流水線的工作流程,是先做什么在做什么
二、什么是面向對象
核心 是對象二字:是一種編程思想,上帝思維,一切皆對象,編程中負責調度和控制
三、面向對象與面向過程的優缺點
面向過程:
優點:程序邏輯性強;復雜的問題簡單化
缺點:維護性差;功能拓展性差
面向對象:
優點:功能拓展性強;維護性高,復用性強
缺點:代碼的復雜度提高了
四、如何創建類和對象
2.0 語法
class A:
def __init__(self,name,age):
self.name = naem
self.age = age
a1 = A() # 類型加括號在初始化階段自動觸發__init__() 方法創建一個空對象, 只有當傳值的時候才會再次觸發__init__()函數的方法,將對象進行初始化賦值 >>> 實列化產生對象的過程
2.1 如何設置屬性
類下的屬性是按照對象的需求進行創造的 ,對象需要什么叫設置什么屬性
2.2 屬性的查找順序
優先找自己> 所在的類>父類
2.3 對象的初始化方法
2.4 綁定方法與非綁定方法
1.綁定給對象的方法,有在對象初始化的時候 2.類中函數的方法是默認綁定給對象用的會默認將實例化的對象傳過去當做函數的第一參數,會用變量名 self 接收
2.當我們需要調用類使用函時加@classmethod 裝飾器下面的函數會自動將<類>作為第一參數傳過來 此時是默認綁定給類用的函數
3.@statimethod 靜態方法 不需要傳參數使用就綁定給誰
二、面向對象三大特性
一、繼承
二、封裝
三、多態
一、繼承
1、什是繼承
定義:描述的是什么 是什么的關系,在程序中描述的是類與類之間的關系,他們之間是存在一定關系的
super()方法
如果你繼承一個已有的類,并且你覆蓋了init 一定要先調用父類的init
子類訪問父類的屬性和方法:先找自己的>所在類>父類>object oject 是所有類的基類
2、為什用繼承:
原因:子類可以使用父類所有未被封裝的屬性和方法 ,提高代碼的重用性,不需要在子類中重寫__init__ 方法》》》實列化的初始賦值
3、繼承語法
a 繼承了b 那么b 就是a 的父類 a 就可以繼承父類b 的所有屬性和未被封裝的方法與數據屬性
4、先抽象在繼承
其實就是一個抽取相同屬性和共用方法的 過程,這個過程是抽象
classA:
name= 'alice'
def __init__(self, name, age):
self.name=name
self.age=ageclassB(A):passa1= A()
5、組合 什么沒有什么的關系
定義:把一個對象當做另一個對象的屬性 這兩不存在任何的關系 不是繼承
是為了使用它的屬性和功能
classDate:def __init__(self,year, month,day):
self.year=year
self.month=month
self.day=daydefinfo(self):print('我是date里的函數')classTeacher:def __init__(self,name, age, num,date):
self.name=name
self.age=age
self.num=num
self.date=datedefchange_score(self):print('修改分數')classStudent:def __init__(self,name,date):
self.date=date
self.name=namedefchoice(self):print('選擇')
d1= Date(2019,7,27)print(d1.year)print(d1.month)print(d1.day)#s1 = Student('koko') # koko想修改分數 或則拿到日期 沒辦法調
s2= Student('koko',d1)print(s2.date.year)print(s2.date.month)print(s2.date.day)
s2.date.info()#類內函數直接執行調用,不需要加括號打印,沒有返回值None 除非自己設置了return值
t1= Teacher('lire',18,10,d1)print(t1.date.year)
t1.date.info()
>>>>>
2019
7
27
2019
7
27
我是date里的函數
2019
我是date里的函數
6、派生
派是子類繼承父類方法和屬性時,自己有重新定義了新的屬性和方法
用的時候優先使用自己的,自己沒有才會使用父類的
7、·覆蓋
子類在繼承父類時 自己有重新定義的屬性和方法 自己的屬性和方法和父類的名字一模一樣
9、新式類和經典類
新式類:默認繼承object 類的叫新式類
python 中默認是新式類 沒有經典類
經典類:沒有繼承oject 類的叫經典類 python2中是用的經典類
10、菱形繼承mro :c3算法
類在查找=順序的時候會按照mro 的查找,深度優先,如果在查找的過程中遇到幾個類同時繼承一個父類廣度優先
二、封裝
2.1何為封裝
1.定義:將丑陋的復雜的,隱私的細節隱藏到內部,對外部提供簡單的使用接口
對外隱藏內部實現,提供函數訪問的簡單的接口2.目的:1.為了保證數據的安全性2.對外隱藏實現細節,隔離復雜度()主要原因就是隔離復雜度)3.什么時候用:1、當有一些數據不希望外界可以直接使用2.當有一些函數不希望給外界使用
4.語法:__屬性名在實列化賦初值
##### 被封裝的內容的特點:
?1.外界不能直接訪問
?2.內部依然可以使用 通過設定函數調用查詢##
2.3 封裝的語法
classPerson:
def __init__(self, name, age, id_number):
self.name=name
self.age=age
self.__id_number= id_number
2.4 封裝的原理:變量在類實列化對象進行初始值賦值的時候就已經將我們隱藏的self._name 封裝成為_父類名__變量名 說以外部在沒有調用函數的基礎下,再次用對象點__name 是根本不可能訪問他的名字的
2.5 訪問私屬性的方法:裝飾器
classPerson:
def __init__(self, name, age, id_number):
self.name=name
self.age=age
self.__id_number=id_number
@property
def id_number(self):returnself.__id_number
p1= Person('coco', 18, 6666) # 類生成對象初識化 賦值 將產生的變量存放在名稱空間中 所以綁定關系在初始化的時候已經確定了
# 封裝是將隱藏的屬進行封裝
方法:
1.如果想要訪問內部已經封裝的屬性一是可以在類的屬性下進行定義一個函數 在函數 內返回 我們的要查找我們封裝好的變量名
def id_number(self):
returnself.__id_number
2. 加@property也是一樣的內部代碼必須設計返回我們需要查找的數據屬性
為什么要使用@property
# 對于一寫封裝的屬性如何取值 和修改以及刪除classIphone:
def __init__(self,kind, price, red):
self.__kind=kind
self.__price=price
self.__red=red
# 方法red ,kind , price
@property
def red(self):returnself.__red
@red.setter
def red(self,new_color):
self.__red=new_color
IP= Iphone('蘋果', 4888, '紅色')
# print(IP.red()) # 函數可以直接訪問內部封裝的東西
# print(IP.__red) # 現在沒有辦法獲取 怎么辦呢>>>可以@Property鴨 這樣就相當于IP.red 偽裝成對象點.red
print(IP.red)
IP.red= '綠色'# print(IP.red)
# print(IP.red)
# print(IP.red)
# print(IP.red)
print(IP.red) # 綠色 夾裝飾器是為了可以可以在外部修改和查看內部的屬性和調用方法
原因是:設計是將函數名設計成和我們要所要訪問的變量名一模一樣>>>加@property后就可以直接對象點函數形
其實就是偽裝讓外部覺得他直接對象點變量名的拿到的變量名指向的內存空間的值,實際情況是我們對外提供了接口,封裝了我們的在內部實現細節。
如何訪問私有化的函數:被封裝了的函數
#目的不讓外部修改內部屬性和方法
classPerson:def __init__(self, name, age, id_number):
self.name=name
self.age=age
self.__id_number =id_number
@propertydefid_number(self):return self.__id_number
def __run(self): #如何訪問封值裝私有化的函數 __run實質變形為:_所屬的類名__函數名
print('running')print('密碼》》》009')def bar(self,y): #好簡單 在函數內部在定義一個函數 他的返回結果就是封裝的函數 可以拿到里面的代碼執行的內容
if y < 100:return self.__run()
>>>>
好簡單 在函數內部在定義一個函數 他的返回結果就是封裝的函數 可以拿到里面的代碼執行的內容
封裝原理:
__run實質變形為:_所屬的類名__函數名
p1._Person__run() # 私有化原理
p1.bar(70) # 通過定義一個新的函數訪問 設置返回值
2.6.封裝計算屬性
#1.計算一個元或者一個長方形的面積
# 計算一個元或者一個長方形的面積classRadio:
def __init__(self,r=10):
self.__r=r
#計算周長
@property
def r(self):returnself.__r
@r.setter
def r(self, new_r):
self.__r=new_r
#計算面積
def ares(self):return 3.14*self.__r**2r1=Radio()
res1=r1.ares()
print(res1)
r1.r= 20# r2= Radio(20) # 內部我們限定死了 所以沒有辦法更改 怎么辦
res=r1.ares()
print(res)
# 現在想把我的 可以通過外部進行改值
# print(r1.R())
# print(r2.R())
print(Radio.__dict__)
2. 計算BMI
#練習: 定義一個類叫做person#包含三個屬性 身高 體重 BMI#BMI的值需要通過計算得來 公式 體重 / 身高的平方
classBaseClass:def __init__(self, high, weight,):
self.high=high
self.weight=weightdefBMI(self):#公式:BMI = 體重(KG)/身高(m)的平方
return self.weight/self.high**2
#實列化對象
person1= BaseClass(1.65, 62)print(person1.BMI())"""當BMI指數為18.5~23.9時屬正常。
成人的BMI數值標準:
過輕:低于18.5 正常:18.5-23.9
過重:24-27 肥胖:28-32"""
2.7 鴨子類型
接口
何為接口:就是如USB接口提供一套統一標準的協議只要你遵循use制定的接口協議,你的設備盡可以通過使用usd 的功能 就可以連入電腦 進項相關操作
#接口:USB提供了一套統一的標準的也稱為協議,只要你遵循的這條套協議你的設備就可以連入電腦使用,不管你是 鼠標還是鍵盤都可以被識操作電腦
classMouse:defopen(self):print('鼠標打開電腦')defclose(self):print('鼠標關閉了')defread(self):print('鼠標獲取關光標')defwrite(self):print('鼠標不支持寫')defpc(usb_server):
usb_server.open()
usb_server.close()
usb_server.write()
usb_server.close()
m=Mouse()
pc(m)#這是外部函數加括號進行傳參
classKeyBord:defopen(self):print('鍵盤打開。。。')defclose(self):print('鍵盤關機了。。。')defread(self):print('獲取按鍵字符。。')defwrite(self):print('鍵盤寫入信息')#鴨子類型屬性也像都很像,方法有像 所以叫做鴨子類型
k=KeyBord()
pc(k)classUdisk:defopen(self):print('u盤啟動了')defclose(self):print('U盤關閉')defread(self):print('讀出數據')defwrite(self):print('寫入數據')
u=Udisk()
pc(u)
抽象 類
定義:abc 抽象類 就是函數體內沒有函數體代碼 沒有任何函數體 定義函數功能 沒有函數內容
# 強制要求子類的函數功能和父類功能一模一樣, 但是我們根據需求可以在子類函數體內 定義添加功能其他功能代碼 抽象類就但是一套統一的接口 要用我的東西 可以 但必須遵循我的協議標準
#接口和抽像類:#何為接口:是一套協議規范,明確子類們應該具備哪些功能,#抽象類是用于強制要求字類必須按照協議中規定的來實現,python 中不推崇
#鴨子類型:既可讓多個不同類對象具備相同屬性和方法對于使用者而言,就可以以不變應萬變,輕松的使用各種對象
"""abc
抽象類的定義:類中包含沒有函體的方法"""
importabcclass AClass(metaclass=abc.ABCMeta):
@abc.abstractmethoddefeat(self):pass@abc.abstractmethoddefeat1(self):pass
classGt(AClass):defeat(self):print('正在吃飯。。。。')defeat1(self):print('111111')whileTrue:
choice= input('調用此功能輸入指令:').strip()if choice == '123456':print('yes')break
else:print('false')continueb= Gt() #無法用抽象方法eat1 去實列化抽象類Gt
b.eat1()
鴨子類型
一個類看起來像鴨子(屬性),走起來也像(方法)就叫鴨子類型
然而,python 不推崇限制咱們的語法規則,我們可以設計成鴨子類型,即讓多個不同類對象具備相同的屬性和方法
對于使用者而言,就是可以以不變應萬變。輕松的是使用各種對象
三、多態
3.1 定義:多個不同的類可以響同一個方法,產生不同的結果
首先強調多態不是一種特殊的語法,而是一種狀態,特征(多個不同的類可以響同一個方法,產生不同的結果)
即多個對象有不同的使用方法
3.2優點:對于使用者而言大大的降低了使用難度
我們之前寫的USB接口下的使用難度(鴨子類型)多的屬于多態
3.3 接口,抽象類 都可以寫出具備多態的代碼,最簡單的就是鴨子類型
案列:
#實列 多態其實就是不同事物可以使用同一種方法,但是產生的結果會不同(觸發個方法的內部執行的內容不同)
classChicken:#同一方法
defdown(self):print('雞下雞蛋。。。')classDuck:defdown(self):print('鴨下鴨蛋。。。')classGoose:defdown(self):print('鵝下鵝蛋。。。')
雞鴨鵝 都具有相同的功能,可以l利用實列化的對象 在內部封裝一個調用接口
對象點自己內部的函數加 括號 執行對應的共能
#實列化對象
c =Chicken()
d=Duck()
g= Goose()
# 調用同一個方法
deffunc(obj):
obj.down()
func(c)
func(d)
func(g)
總結
以上是生活随笔為你收集整理的python中面向对象的缺点_python中的面向对象和面向过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【2023校招刷题】常见面试问题总结(一
- 下一篇: STC15W单片机防丢语音报警GPS北斗