溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python中使用class(),面向?qū)ο笥惺裁磧?yōu)勢

發(fā)布時(shí)間:2020-07-02 05:11:46 來源:網(wǎng)絡(luò) 閱讀:311 作者:Python熱愛者 欄目:編程語言

首先我是辣雞,然后這個(gè)問題的確有點(diǎn)意思

首先,類是一個(gè)集合,包含了數(shù)據(jù),操作描述的一個(gè)抽象集合

你可以首先只把類當(dāng)做一個(gè)容器來使用

class Cycle:
   def __init__(self,r):
       self.pi=3.14
       self.r=r
a=Cycle(4)
b=Cycle(7)

你看,我們定義了一個(gè) Cycle 類,我們現(xiàn)在只是將它當(dāng)做一個(gè)數(shù)據(jù)集合來用,我們利用其實(shí)例之間彼此數(shù)據(jù)隔離的特性來保證具體的實(shí)例數(shù)據(jù)彼此不污染。好了你現(xiàn)在想問,為什么我們要用數(shù)據(jù)集合來放數(shù)據(jù)

好了,我們來看看沒有類之前我們會(huì)怎么樣,假設(shè)我們現(xiàn)在要計(jì)算圓的面積

'''
遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 
尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書!
'''
def square(r,pi):
   return pi * (r**2)
PI=3.14
a_r=4
a_square=square(a_r,PI)
b_r=7
b_square=square(b_r,PI)

看起來沒有問題,好了,現(xiàn)在問題來了,假如,你現(xiàn)在要計(jì)算很多圓的面積,那么你是不是發(fā)現(xiàn),不斷的用變量命來隔離數(shù)據(jù)方式變得越來越臟了。而且你發(fā)現(xiàn)是不是有很多冗余的代碼

好了我們這么改一改

class Cycle:
   def __init__(self,r):
       self.pi=3.14
       self.r=r

def square(value):
   if not isinstance(value,Cycle):
       raise ValueError("value muse be Cycle instace")
   value.square=value.pi * (value.r**2)

a=Cycle(4)
b=Cycle(7)

square(a)
square(b)

好了,你有沒有覺得現(xiàn)在清晰了一點(diǎn)。

好了,現(xiàn)在我們現(xiàn)在還可以改一下

'''
遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 
尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書!
'''
class Cycle:
   def __init__(self,r):
       self.pi=3.14
       self.r=r
   def square(self,value):
       return self.pi * (self.r**2)

好了,現(xiàn)在你可能迷惑了,我們?yōu)樯兑?square 函數(shù)放在類中?

好了,我現(xiàn)在要計(jì)算長方形,原型,梯形各種各樣二維幾何圖形的面積,這樣該怎么寫???

你想了想我們之前說的將類作為數(shù)據(jù)容器,你想了想寫了如下的代碼

class Rectangle:
   def __init__(self,length,height):
       self.length=length
       self.height=height
class Cycle:
   def __init__(self,r):
       self.pi=3.14
       self.r=r
def rec_square(value):
   if not isinstance(value,Rectangle):
       raise ValueError("value muse be Rectangle instace")
   value.square=value.length * value.height
def cycle_square(value):
   if not isinstance(value,Cycle):
       raise ValueError("value muse be Cycle instace")
   value.square=value.pi * (value.r**2)

你想一想,這樣是不是感覺如果計(jì)算需求越來越多,代碼是不是還是會(huì)越來越臟?

如果我們將函數(shù)放在類里,并且用繼承的特性,我們可以寫出這樣的代碼

'''
遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 
尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書!
'''
class Geometry:
   def get_square(self):
       raise NotImplementedError

class Rectangle(Geometry):
   def __init__(self,length,height):
       self.length=length
       self.height=height
   def get_square(self):
       return self.length*self.height

class Cycle(Geometry):
   def __init__(self,r):
       self.pi=3.14
       self.r=r
   def get_square(self):
       return self.pi * (self.r**2)

def square(value):
   if not isinstance(value,Geometry):
       raise ValueError("value muse be Geometry instace")
   value.square=value.get_square()

你看,我們現(xiàn)在只需要給用戶暴露一個(gè)統(tǒng)一的接口,用戶(用戶也以是我們自己)不需要關(guān)心怎么樣選擇正確的函數(shù),他只需要調(diào)用統(tǒng)一的 square 函數(shù),就可以獲取到具體的面積,是不是輕松很多了??

所以,類,它是對(duì)數(shù)據(jù),操作的一種封裝,這個(gè)封裝的意義在于我們可以去更好的優(yōu)化代碼結(jié)構(gòu)。

好了再舉一個(gè)例子,我們可以用類來控制訪問權(quán)限

class People:
   def __init__(self,website):
       self.__favorite_website="1024.com"
   def bad_or_not(self):
       return self.__favorite_website=="1024.com"

你看,我們用 private 變量,來確保外部沒法直接訪問一些敏感數(shù)據(jù)(實(shí)際上 Python 里 private 并不嚴(yán)格,hook 一下還是可以訪問的)

好,在舉一個(gè)例子

'''
遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 
尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書!
'''
class People:
   def __init__(self,website):
       self.__favorite_website="1024.com"
   def bad_or_not(self):
       return self.__favorite_website=="1024.com"
   @property
   def favorite_website(self):
       return self.__favorite_website
   @favorite_website.setter
   def favorite_website(self,value):
       if value=="1024.com":
           raise ValueError("你不能去草榴,兄弟,你營養(yǎng)不足")
       self.__favorite_website=value

你看,我們現(xiàn)在很方便的實(shí)現(xiàn)在設(shè)置數(shù)據(jù)值的時(shí)候,對(duì)其過濾。

撤了這么多,回到你的問題

首先A君說的沒毛病,但我想知道僅僅使用函數(shù)錘子,螺絲刀來完成一個(gè)項(xiàng)目比使用Class工廠+函數(shù)錘子來完成一個(gè)項(xiàng)目的效率會(huì)更低么?
理由是什么?大神在什么時(shí)候會(huì)考慮使用Class來提高代碼的“執(zhí)行效率”和代碼的“可讀性”。回歸實(shí)際情況,我很多時(shí)候都是調(diào)用同一個(gè)函數(shù)/方法去輸出某個(gè)結(jié)果。
至今還想不出為什么調(diào)用Class會(huì)更方便?(PS:本人大菜鳥,寫了上千行代碼了,但仍然搞不懂什么情況下需要用到Class類。也曾嘗試在自己的代碼中強(qiáng)行加入Class輸出結(jié)果
但感覺不靈活,而且要寫的代碼明顯多了也不便于理解。求大神舉例,碾壓我的無知?。君說大型項(xiàng)目不使用Class調(diào)用對(duì)象會(huì)累死,到底這個(gè)“累死”體現(xiàn)在哪里?

首先一個(gè)問題,我整個(gè)答案里所寫的這些代碼,不用面向?qū)ο筮@一套能不能實(shí)現(xiàn)?

很明顯,能。

但是實(shí)現(xiàn)的干凈么?個(gè)人覺得不干凈。

項(xiàng)目規(guī)格上去后,我們?nèi)绻凑諅鹘y(tǒng)的方式進(jìn)行開發(fā),務(wù)必要多重檢查,確保自己不會(huì)手抖調(diào)用了錯(cuò)誤的東西。而 OOP 這一套思想,其實(shí)就是通過利用合適的代碼結(jié)構(gòu)和封裝,某種程度上來講是減少我們犯錯(cuò)的可能。

同時(shí),現(xiàn)在開發(fā)基本都不是一個(gè)人的單打獨(dú)斗,你寫的代碼可能會(huì)被其余人使用與維護(hù)。我們有個(gè)前提,要假設(shè)使用維護(hù)你代碼的人都是傻逼。我們要適當(dāng)?shù)姆庋b代碼,優(yōu)化結(jié)構(gòu),讓使用者盡可能的少犯錯(cuò)、

所以最后,無論是各個(gè)語言的變量命名規(guī)則也好,還是 OOP 這一套范式也好。其本質(zhì)是在自由度與可讀性可維護(hù)性之間的一種相對(duì)較優(yōu)的妥協(xié),這種妥協(xié)根本的目的就在于通過規(guī)范化的操作與封裝,減少團(tuán)隊(duì)開發(fā)維護(hù)的成本,優(yōu)化開發(fā)體驗(yàn)。

另外,關(guān)于開發(fā)這一套還有個(gè)老生常談的問題過度封裝。我個(gè)人的觀點(diǎn)是在你知道什么是 過度封裝 之前,你沒必要考慮這個(gè)問題,按照教科書和開源代碼里的結(jié)構(gòu),去不斷封裝優(yōu)化你的代碼。

面向?qū)ο蟆「菀资褂谩?,缺點(diǎn)就是 換一個(gè)開發(fā)人,難維護(hù),很難理解前面人的思維,出了錯(cuò)不好找位置

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI