python面向对象还是过程_Python学习————面向对象和面向过程
一、面向過程和面向對象
面向過程:
核心是"過程"二字
過程的終極奧義就是將程序流程化
過程是"流水線",用來**分步驟解決問題**的
面向對象:
? 核心是"對象"二字
? 對象的終極奧義就是將程序"整合"
? 對象是"容器",用來盛放數(shù)據(jù)與功能的
?
? 類也是"容器",該容器用來存放同類對象共有的數(shù)據(jù)與功能
二 、什么是面向對象的程序設計及為什么要有它
面向過程的程序設計:
核心是過程二字,過程指的是解決問題的步驟,即先干什么再干什么......面向過程的設計就好比精心設計好一條流水線,是一種機械式的思維方式。
優(yōu)點:
復雜度的問題流程化,進而簡單化(一個復雜的問題,分成一個個小的步驟去實現(xiàn),實現(xiàn)小的步驟將會非常簡單)
缺點:
一套流水線或者流程就是用來解決一個問題,生產(chǎn)汽水的流水線無法生產(chǎn)汽車,即便是能,也得是大改,改一個組件,牽一發(fā)而動全身。
應用場景:
一旦完成基本很少改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向對象的程序設計:
核心是對象二字,,對象是特征與技能的結合體,基于面向對象設計程序就好比在創(chuàng)造一個世界,你就是這個世界的上帝,存在的皆為對象,不存在的也可以創(chuàng)造出來,與面向過程機械式的思維方式形成鮮明對比,面向對象更加注重對現(xiàn)實世界的模擬,是一種“上帝式”的思維方式。
優(yōu)點:
解決了程序的擴展性。對某一個對象單獨修改,會立刻反映到整個體系中,如對游戲中一個人物參數(shù)的特征和技能修改都很容易。
缺點:
編程的復雜度遠高于面向過程,不了解面向對象而立即上手基于它設計程序,極容易出現(xiàn)過度設計的問題。一些擴展性要求低的場景使用面向對象會徒增編程難度,比如管理linux系統(tǒng)的shell腳本就不適合用面向對象去設計,面向過程反而更加適合。
無法向面向過程的程序設計流水線式的可以很精準的預測問題的處理流程與結果,面向對象的程序一旦開始就由對象之間的交互解決問題,即便是上帝也無法準確地預測最終結果。于是我們經(jīng)常看到對戰(zhàn)類游戲,新增一個游戲人物,在對戰(zhàn)的過程中極容易出現(xiàn)陰霸的技能,一刀砍死3個人,這種情況是無法準確預知的,只有對象之間交互才能準確地知道最終的結果。
應用場景:
需求經(jīng)常變化的軟件,一般需求的變化都集中在用戶層,互聯(lián)網(wǎng)應用,企業(yè)內部軟件,游戲等都是面向對象的程序設計大顯身手的好地方
代碼實例
# 學生的功能
def tell_stu_info(stu_obj):
print('學生信息:名字:%s 年齡:%s 性別:%s' %(
stu_obj['stu_name'],
stu_obj['stu_age'],
stu_obj['stu_gender']
))
def set_info(stu_obj,x,y,z):
stu_obj['stu_name']=x
stu_obj['stu_age']=y
stu_obj['stu_gender']=z
stu_obj={
'stu_school':'oldboy',
'stu_name':'egon',
'stu_age':18,
'stu_gender':'male',
'tell_stu_info': tell_stu_info,
'set_info':set_info
}
stu1_obj={
'stu_school':'oldboy',
'stu_name':'lili',
'stu_age':19,
'stu_gender':'female',
'tell_stu_info': tell_stu_info,
'set_info':set_info
}
三 類與對象
類即類別/種類,是面向對象分析和設計的基石,如果多個對象有相似的數(shù)據(jù)與功能,那么該多個對象就屬于同一種類。有了類的好處是:我們可以把同一類對象相同的數(shù)據(jù)與功能存放到類里,而無需每個對象都重復存一份,這樣每個對象里只需存自己獨有的數(shù)據(jù)即可,極大地節(jié)省了空間。所以,如果說對象是用來存放數(shù)據(jù)與功能的容器,那么類則是用來存放多個對象相同的數(shù)據(jù)與功能的容器。
綜上所述,雖然我們是先介紹對象后介紹類,但是需要強調的是:在程序中,必須要事先定義類,然后再調用類產(chǎn)生對象(調用類拿到的返回值就是對象)。產(chǎn)生對象的類與對象之間存在關聯(lián),這種關聯(lián)指的是:對象可以訪問到類中共有的數(shù)據(jù)與功能,所以類中的內容仍然是屬于對象的,類只不過是一種節(jié)省空間、減少代碼冗余的機制,面向對象編程最終的核心仍然是去使用對象。
四 面向對象編程
類的定義與實例化
面向對象的基本思路就是把程序中要用到的、相關聯(lián)的數(shù)據(jù)與功能整合到對象里,然后再去使用,但程序中要用到的數(shù)據(jù)以及功能那么多,如何找到相關連的呢?我需要先提取選課系統(tǒng)里的角色:學生、老師、課程等,然后顯而易見的是:學生有學生相關的數(shù)據(jù)于功能,老師有老師相關的數(shù)據(jù)與功能,我們單以學生為例,
# 學生1:
數(shù)據(jù):
學校=清華大學
姓名=李建剛
性別=男
年齡=28
功能:
選課
# 學生2:
數(shù)據(jù):
學校=清華大學
姓名=王大力
性別=女
年齡=18
功能:
選課
# 學生3:
數(shù)據(jù):
學校=清華大學
姓名=牛嗷嗷
性別=男
年齡=38
功能:
選課
我們可以總結出一個學生類,用來存放學生們相同的數(shù)據(jù)與功能
# 學生類
相同的特征:
學校=清華大學
相同的功能:
選課
基于上述分析的結果,我們接下來需要做的就是在程序中定義出類,然后調用類產(chǎn)生對象
類體最常見的是變量的定義和函數(shù)的定義,但其實類體可以包含任意Python代碼,類體的代碼在類定義階段就會執(zhí)行,因而會產(chǎn)生新的名稱空間用來存放類中定義的名字,可以打印Student.__dict__來查看類這個容器內盛放的東西
>>> print(Student.__dict__)
{..., 'school': '清華大學', 'choose': , ...}
調用類的過程稱為將類實例化,拿到的返回值就是程序中的對象,或稱為一個實例
>>> stu1=Student() # 每實例化一次Student類就得到一個學生對象
>>> stu2=Student()
>>> stu3=Student()
如此stu1、stu2、stu3全都一樣了(只有類中共有的內容,而沒有各自獨有的數(shù)據(jù)),想在實例化的過程中就為三位學生定制各自獨有的數(shù)據(jù):姓名,性別,年齡,需要我們在類內部新增一個__init__方法,如下
class Student:
school='清華大學'
#該方法會在對象產(chǎn)生之后自動執(zhí)行,專門為對象進行初始化操作,可以有任意代碼,但一定不能返回非None的值
def __init__(self,name,sex,age):
self.name=name
self.sex=sex
self.age=age
def choose(self):
print('%s is choosing a course' %self.name)
然后我們重新實例出三位學生
>>> stu1=Student('李建剛','男',28)
>>> stu2=Student('王大力','女',18)
>>> stu3=Student('牛嗷嗷','男',38)
單拿stu1的產(chǎn)生過程來分析,調用類會先產(chǎn)生一個空對象stu1,然后將stu1連同調用類時括號內的參數(shù)一起傳給Student.init(stu1,’李建剛’,’男’,28)
def __init__(self, name, sex, age):
self.name = name # stu1.name = '李建剛'
self.sex = sex # stu1.sex = '男'
self.age = age # stu1.age = 28
會產(chǎn)生對象的名稱空間,同樣可以用__dict__查看
>>> stu1.__dict__
{'name': '李建剛', 'sex': '男', 'age': 28}
至此,我們造出了三個對象與一個類,對象存放各自獨有的數(shù)據(jù),類中存放對象們共有的內容
五 屬性查找
類有兩種屬性:數(shù)據(jù)屬性和函數(shù)屬性
類的數(shù)據(jù)屬性是所有對象共享的
類的函數(shù)屬性是綁定給對象用的
#類的數(shù)據(jù)屬性是所有對象共享的,id都一樣
print(id(OldboyStudent.school))
print(id(s1.school))
print(id(s2.school))
print(id(s3.school))
'''
4377347328
4377347328
'''
#類的函數(shù)屬性是綁定給對象使用的,obj.method稱為綁定方法,內存地址都不一樣
#ps:id是python的實現(xiàn)機制,并不能真實反映內存地址,如果有內存地址,還是以內存地址為準
print(OldboyStudent.learn)
print(s1.learn)
print(s2.learn)
print(s3.learn)
'''
>
>
>
'''
六、:封裝
封裝:面向對象三大特征 最核心 的一個特性
封裝 <=> 整合
1:將封裝的屬性進行隱藏操作
1.如何隱藏:在屬性名前加__前綴,就會實現(xiàn)一個對外隱藏屬性效果**
該隱藏需要注意的問題:
I:在類外部無法直接訪問雙下滑線開頭的屬性,但知道了類名和屬性名就可以拼出名字:_類名__屬性,然后就可以訪問了,如Foo._A__N,所以說這種操作并沒有嚴格意義上地限制外部訪問,僅僅只是一種語法意義上的變形。
class Foo:
__x = 1 # _Foo__x
def __f1(self): # _Foo__f1
print('from test')
print(Foo.__dict__) # {'__module__': '__main__', '_Foo__x': 1, '_Foo__f1': , '__dict__': , '__weakref__': , '__doc__': None}
print(Foo._Foo__x) # 1
print(Foo._Foo__f1) #
這種隱藏對外不對內,因為__開頭的屬性會在檢查類體代碼語法時統(tǒng)一發(fā)生變形
class Foo:
__x = 1 # _Foo__x = 1
def __f1(self): # _Foo__f1
print('from test')
def f2(self):
print(self.__x) # print(self._Foo__x)
print(self.__f1) # print(self._Foo__f1)
# print(Foo.__x) # AttributeError: type object 'Foo' has no attribute '__x'
# print(Foo.__f1) # AttributeError: type object 'Foo' has no attribute '__f1'
obj=Foo() # 1
obj.f2() # >
class Foo:
__x = 1 # _Foo__x = 1
def __f1(self): # _Foo__f1
print('from test')
def f2(self):
print(self.__x) # print(self._Foo__x)
print(self.__f1) # print(self._Foo__f1)
Foo.__y=3
print(Foo.__dict__) # {'__module__': '__main__', '_Foo__x': 1, '_Foo__f1': , 'f2': , '__dict__': , '__weakref__': , '__doc__': None, '__y': 3}
print(Foo.__y) # {'__module__': '__main__', '_Foo__x': 1, '_Foo__f1': , 'f2': , '__dict__': , '__weakref__': , '__doc__': None, '__y': 3}
class Foo:
__x = 1 # _Foo__x = 1
def __init__(self, name, age):
self.__name = name
self.__age = age
obj = Foo('egon', 18)
print(obj.__dict__) # {'_Foo__name': 'egon', '_Foo__age': 18}
# print(obj.name, obj.age) # AttributeError: 'Foo' object has no attribute 'name'
2.為何要隱藏
隱藏數(shù)據(jù)屬性"將數(shù)據(jù)隱藏起來就限制了類外部對數(shù)據(jù)的直接操作,然后類內應該提供相應的接口來允許類外部間接地操作數(shù)據(jù),接口之上可以附加額外的邏輯來對數(shù)據(jù)的操作進行嚴格地控制:
# 設計者:egon
class People:
def __init__(self, name):
self.__name = name
def get_name(self):
# 通過該接口就可以間接地訪問到名字屬性
# print('小垃圾,不讓看')
print(self.__name)
def set_name(self,val):
if type(val) is not str:
print('小垃圾,必須傳字符串類型')
return
self.__name=val
# 使用者:王鵬
obj = People('egon')
# print(obj.name) # 無法直接用名字屬性
# obj.set_name('EGON')
obj.set_name(123123123)
obj.get_name()
# II、隱藏函數(shù)/方法屬性:目的的是為了隔離復雜度
總結
以上是生活随笔為你收集整理的python面向对象还是过程_Python学习————面向对象和面向过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: visual studio输入法打不了中
- 下一篇: string 中的offset_Kafk