<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何通俗的理解面向?qū)ο缶幊?/h1>

          共 11285字,需瀏覽 23分鐘

           ·

          2021-07-14 17:12

          點(diǎn)擊上方小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時(shí)間送達(dá)

          本文轉(zhuǎn)自:磐創(chuàng)AI

          面向?qū)ο缶幊袒騉OP對(duì)于初學(xué)者來(lái)說(shuō)可能是一個(gè)很難理解的概念。這主要是因?yàn)楹芏嗟胤蕉紱](méi)有正確的解釋。通常很多書籍都是從解釋OOP開始,討論三大術(shù)語(yǔ):封裝、繼承和多態(tài)性。但是當(dāng)這本書能夠解釋這些話題的時(shí)候,任何一個(gè)剛剛開始的人都會(huì)感到失落。

          所以,我想讓程序員、數(shù)據(jù)科學(xué)家和蟒蛇愛(ài)好者們更容易理解這個(gè)概念。我打算這樣做的方法是去掉所有的行話,并通過(guò)一些例子。我將從解釋類和對(duì)象開始。然后我將解釋為什么類在各種情況下都很重要,以及它們是如何解決一些基本問(wèn)題的。這樣,讀者也能在帖子末尾理解這三大術(shù)語(yǔ)。

          在這個(gè)名為Python Shorts的系列文章中,我將解釋Python提供的一些簡(jiǎn)單但非常有用的構(gòu)造、一些基本技巧以及我在數(shù)據(jù)科學(xué)工作中經(jīng)常遇到的一些用例。

          這篇文章是關(guān)于解釋OOP的外行方式。

          什么是對(duì)象和類

          簡(jiǎn)單地說(shuō),Python中的一切都是對(duì)象,類是對(duì)象的藍(lán)圖。所以當(dāng)我們寫下:

          a = 2
          b = "Hello!"

          我們正在創(chuàng)建一個(gè)int類的對(duì)象a,該對(duì)象的值為2,str類的對(duì)象b的值為“Hello!”. 當(dāng)我們?cè)谀J(rèn)情況下用兩個(gè)引號(hào)來(lái)提供字符串。

          除此之外,我們中的許多人最終都會(huì)在沒(méi)有意識(shí)到的情況下使用類和對(duì)象。例如,當(dāng)你使用任何scikit-learn模型時(shí),實(shí)際上是在使用一個(gè)類。

          clf = RandomForestClassifier()
          clf.fit(X,y)

          這里的分類器clf是一個(gè)對(duì)象,fit是一個(gè)在RandomForestClassifier類中定義的方法

          為什么要使用類

          因此,我們?cè)谑褂肞ython時(shí)經(jīng)常使用它們。但為什么呢。類是怎么回事?我可以用函數(shù)做同樣的事情嗎?

          是的,你可以。但是與函數(shù)相比,類確實(shí)為你提供了很多功能。舉個(gè)例子,str類有很多為對(duì)象定義的函數(shù),我們只需按tab鍵就可以訪問(wèn)這些函數(shù)。人們也可以編寫所有這些函數(shù),但是那樣的話,只按tab鍵就不能使用它們了。

          類的這個(gè)屬性稱為封裝。從Wikipedia來(lái)看,封裝是指將數(shù)據(jù)與操作該數(shù)據(jù)的方法捆綁在一起,或者限制對(duì)對(duì)象某些組件的直接訪問(wèn)。

          所以這里str類綁定了數(shù)據(jù)(“Hello!)以及所有對(duì)我們的數(shù)據(jù)進(jìn)行操作的方法。我會(huì)在帖子的最后解釋聲明的第二部分。同樣,RandomForestClassifier 類將所有的方法(fit、predict等)捆綁在一起

          除此之外,類的使用還可以幫助我們使代碼更加模塊化和易于維護(hù)。假設(shè)我們要?jiǎng)?chuàng)建一個(gè)像Scikit-Learn這樣的庫(kù)。我們需要?jiǎng)?chuàng)建許多模型,每個(gè)模型都有一個(gè)fit和predict方法。如果不使用類,我們將為每個(gè)不同的模型提供許多函數(shù),例如:

          RFCFit
          RFCPredict
          SVCFit
          SVCPredict
          LRFit
          LRPredict 

          and so on.

          這種代碼結(jié)構(gòu)只是一場(chǎng)噩夢(mèng),因此Scikit Learn將每個(gè)模型定義為一個(gè)具有fit和predict方法的類。

          創(chuàng)建類

          所以,現(xiàn)在我們了解了為什么要使用類,它們是如何如此重要,我們?nèi)绾握嬲_始使用它們?所以,創(chuàng)建一個(gè)類非常簡(jiǎn)單。下面是你將要編寫的任何類的樣板代碼:

          class myClass:
              
              def __init__(self, a, b):
                  self.a = a
                  self.b = b
                  
              def somefunc(self, arg1, arg2):
                  # 這里有些代碼

          我們?cè)谶@里看到很多新的關(guān)鍵字。主要是class、__init__self。這些是什么?同樣,通過(guò)一些例子很容易解釋。

          假設(shè)你在一家有很多賬戶的銀行工作。我們可以創(chuàng)建一個(gè)名為account的類,用于處理任何帳戶。例如,下面我創(chuàng)建了一個(gè)基本的玩具類帳戶,它為用戶存儲(chǔ)數(shù)據(jù),即帳戶名和余額。它還為我們提供了兩種銀行存款/取款的方法。一定要通讀一遍。它遵循與上面代碼相同的結(jié)構(gòu)。

          class Account:
              
              def __init__(self, account_name, balance=0):
                  self.account_name = account_name
                  self.balance = balance
              
              def deposit(self, amount):
                  self.balance += amount
              
              def withdraw(self,amount):
                  if amount <= self.balance:
                      self.balance -= amount
                  else:
                      print("Cannot Withdraw amounts as no funds!!!")

          我們可以使用以下方法創(chuàng)建一個(gè)名為Rahul且金額為100的帳戶:

          myAccount = Account("Rahul",100)

          我們可以使用以下方法訪問(wèn)此帳戶的數(shù)據(jù):

          但是,如何將這些屬性balance和account_name分別設(shè)置為100和“Rahul”?我們從來(lái)沒(méi)有調(diào)用過(guò)__init__方法,那么為什么對(duì)象會(huì)獲得這些屬性?這里的答案是,只要我們創(chuàng)建對(duì)象,它就會(huì)運(yùn)行。因此,當(dāng)我們創(chuàng)建myAccount時(shí),它還會(huì)自動(dòng)運(yùn)行函數(shù)__init__

          所以現(xiàn)在我們明白了,讓我們?cè)囍嬉恍╁X到我們的賬戶里。我們可以通過(guò):

          我們的余額上升到200英鎊。但是你有沒(méi)有注意到,我們的函數(shù)deposit需要兩個(gè)參數(shù),即self和amount,但是我們只提供了一個(gè)參數(shù),而且仍然有效。

          那么,這個(gè)self是什么?有self的方法是用一種不同的方式調(diào)用同一個(gè)函數(shù)。下面,我調(diào)用屬于類account的同一個(gè)函數(shù)deposit,并向它提供myAccount對(duì)象和amount?,F(xiàn)在函數(shù)需要兩個(gè)參數(shù)。

          我們的賬戶余額如預(yù)期增加了100。所以這是我們調(diào)用的同一個(gè)函數(shù)?,F(xiàn)在,只有self和myAccount是完全相同的對(duì)象時(shí),才會(huì)發(fā)生這種情況。我調(diào)用的時(shí)候我的賬戶存款(100)。Python為函數(shù)調(diào)用提供與參數(shù)self相同的對(duì)象myAccount。這就是為什么self.balance在函數(shù)定義中真正指的是myAccount.balance.

          但是,仍然存在一些問(wèn)題

          我們知道如何創(chuàng)建類,但是還有一個(gè)重要的問(wèn)題我還沒(méi)有提到。

          所以,假設(shè)你正在與蘋果iPhone部門合作,并且必須為每種iPhone型號(hào)創(chuàng)建一個(gè)不同的類。對(duì)于這個(gè)簡(jiǎn)單的例子,讓我們假設(shè)我們的iPhone的第一個(gè)版本目前只做一件事——打電話并存儲(chǔ)。我們可以這樣寫:

          class iPhone:
              
              def __init__(self, memory, user_id):
                   self.memory = memory
                   self.mobile_id = user_id
                  
              def call(self, contactNum):
                   # 這里有些實(shí)現(xiàn)

          現(xiàn)在,蘋果計(jì)劃推出iPhone1,這款iPhone機(jī)型引入了一項(xiàng)新功能——拍照功能。一種方法是復(fù)制粘貼上述代碼并創(chuàng)建一個(gè)新的類iPhone1,如下所示:

          class iPhone1:
              
              def __init__(self, memory, user_id):
                   self.memory = memory
                   self.mobile_id = user_id
                   self.pics = []
                   
              def call(self, contactNum):
                   # 這里有些實(shí)現(xiàn)
                   
              def click_pic(self):
                   # 這里有些實(shí)現(xiàn)
                   pic_taken = ...
                   self.pics.append(pic_taken)

          但正如你所看到的,這是大量不必要的代碼重復(fù)(上面用粗體顯示),Python有一個(gè)消除代碼重復(fù)的解決方案。編寫iPhone1類的一個(gè)好方法是:

          Class iPhone1(iPhone):
              
              def __init__(self,memory,user_id):
                   super().__init__(memory,user_id)
                   self.pics = []
                  
              def click_pic(self):
                   # 這里有些實(shí)現(xiàn)
                   pic_taken = ...
                   self.pics.append(pic_taken)

          這就是繼承的概念。根據(jù)Wikipedia的說(shuō)法:繼承是將一個(gè)對(duì)象或類基于另一個(gè)保留類似實(shí)現(xiàn)的對(duì)象或類的機(jī)制。簡(jiǎn)單地說(shuō),iPhone1現(xiàn)在可以訪問(wèn)類iPhone中定義的所有變量和方法。

          在本例中,我們不必進(jìn)行任何代碼復(fù)制,因?yàn)槲覀円呀?jīng)從父類iPhone繼承(獲取)了所有方法。因此,我們不必再次定義調(diào)用函數(shù)。另外,我們不使用super在函數(shù)中設(shè)置mobile_uid和內(nèi)存。

          **super().__init__(memory,user_id)**是什么?

          在現(xiàn)實(shí)生活中,你的初始函數(shù)不是這些漂亮的兩行函數(shù)。你將需要在類中定義許多變量/屬性,并且復(fù)制并粘貼子類(這里是iphone1)會(huì)很麻煩。因此存在super().。這里super().__init__()實(shí)際上在這里調(diào)用父iPhone類的**__init__**方法。因此,在這里,當(dāng)類iPhone1的__init__函數(shù)運(yùn)行時(shí),它會(huì)自動(dòng)使用父類的__init__函數(shù)設(shè)置類的memory和user_id。

          我們?cè)贛L/DS/DL中的哪里可以看到?下面是我們創(chuàng)建PyTorch模型。此模型繼承了nn.Module類,并使用super調(diào)用該類的__init__函數(shù)。

          class myNeuralNet(nn.Module):

              def __init__(self):
                  super().__init__()
                  # 在這里定義所有層
                  self.lin1 = nn.Linear(78430)
                  self.lin2 = nn.Linear(3010)
                  
              def forward(self, x):
                  # 在此處連接層輸出以定義前向傳播
                  x = self.lin1(x)
                  x = self.lin2(x)
                  return x

          但什么是「多態(tài)」?我們?cè)絹?lái)越了解類是如何工作的,所以我想我現(xiàn)在就試著解釋多態(tài)??聪旅娴念?。

          import math

          class Shape:
              def __init__(self, name):
                  self.name = name

              def area(self):
                  pass
                  
              def getName(self):
                  return self.name
                  
          class Rectangle(Shape):
              def __init__(self, name, length, breadth):
                  super().__init__(name)
                  self.length = length
                  self.breadth = breadth
                  
              def area(self):
                  return self.length*self.breadth

          class Square(Rectangle):
              def __init__(self, name, side):
                  super().__init__(name,side,side)
                  
          class Circle(Shape):
              def __init__(self, name, radius):
                  super().__init__(name)
                  self.radius = radius

              def area(self):
                  return pi*self.radius**2

          這里我們有基類Shape和其他派生類-Rectangle和Circle。另外,看看我們?nèi)绾卧赟quare類中使用多個(gè)級(jí)別的繼承,Square類是從Rectangle派生的,而Rectangle又是從Shape派生的。每個(gè)類都有一個(gè)名為area的函數(shù),它是根據(jù)形狀定義的。

          因此,通過(guò)Python中的多態(tài)性,一個(gè)同名函數(shù)可以執(zhí)行多個(gè)任務(wù)的概念成為可能。事實(shí)上,這就是多態(tài)性的字面意思:“具有多種形式的東西”。所以這里我們的函數(shù)area有多種形式。

          多態(tài)性與Python一起工作的另一種方式是使用isinstance方法。因此,使用上面的類,如果我們這樣做:

          因此,對(duì)象mySquare的實(shí)例類型是方形、矩形和形狀。因此對(duì)象是多態(tài)的。這有很多好的特性。例如,我們可以創(chuàng)建一個(gè)與Shape對(duì)象一起工作的函數(shù),它將通過(guò)使用多態(tài)性完全處理任何派生類(Square、Circle、Rectangle等)。

          更多信息

          為什么我們看到函數(shù)名或?qū)傩悦詥蜗聞澗€和雙下劃線開頭?有時(shí)我們想讓類中的屬性和函數(shù)私有化,而不允許用戶看到它們。這是封裝的一部分,我們希望“限制對(duì)對(duì)象某些組件的直接訪問(wèn)”。例如,假設(shè)我們不想讓用戶看到我們的iPhone創(chuàng)建后的memory(RAM)。在這種情況下,我們使用變量名中的下劃線創(chuàng)建屬性。

          因此,當(dāng)我們以下面的方式創(chuàng)建iPhone類時(shí),你將無(wú)法訪問(wèn)你的memory或ipython私有函數(shù),因?yàn)樵搶傩袁F(xiàn)在使用_

          但你仍然可以使用(盡管不建議使用)更改變量值,

          你還可以使用私有函數(shù)myphone._privatefunc()。如果要避免這種情況,可以在變量名前面使用雙下劃線。例如,在調(diào)用print(myphone.__memory)下面拋出一個(gè)錯(cuò)誤。此外,你無(wú)法使用myphone更改對(duì)象的內(nèi)部數(shù)據(jù)。myphone.__memory = 1。

          但是,正如你所見(jiàn),你可以在類定義中的函數(shù)setMemory中訪問(wèn)和修改self.__memory

          結(jié)論

          我希望這對(duì)你理解類很有用。仍然有很多類需要我在下一篇關(guān)于magic方法的文章中討論。敬請(qǐng)期待。另外,總結(jié)一下,在這篇文章中,我們學(xué)習(xí)了OOP和創(chuàng)建類以及OOP的各種基礎(chǔ)知識(shí):

          • 封裝:對(duì)象包含自身的所有數(shù)據(jù)。

          • 繼承:我們可以創(chuàng)建一個(gè)類層次結(jié)構(gòu),其中父類的方法傳遞給子類

          • 多態(tài):函數(shù)有多種形式,或者對(duì)象可能有多種類型。

          為了結(jié)束這篇文章,我會(huì)給你一個(gè)練習(xí),讓你去實(shí)現(xiàn),因?yàn)槲艺J(rèn)為這可能會(huì)為你澄清一些概念。創(chuàng)建一個(gè)類,使你可以使用體積和曲面面積管理三維對(duì)象(球體和立方體)?;緲影宕a如下所示:

          import math

          class Shape3d:
              def __init__(self, name):
                  self.name = name
              def surfaceArea(self):
                  pass
                  
              def volume(self):
                  pass
              
              def getName(self):
                  return self.name
                  
          class Cuboid():
              pass
          class Cube():
              pass
                  
          class Sphere():
              pass

          如果你想了解更多關(guān)于Python的知識(shí),我想從密歇根大學(xué)(universityofmichigan)調(diào)出一門關(guān)于學(xué)習(xí)中級(jí)Python的優(yōu)秀課程:https://bit.ly/shrea

          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺(jué)、目標(biāo)跟蹤、生物視覺(jué)、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目52講
          小白學(xué)視覺(jué)公眾號(hào)后臺(tái)回復(fù):Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車道線檢測(cè)、車輛計(jì)數(shù)、添加眼線、車牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺(jué)實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺(jué)。

          下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
          小白學(xué)視覺(jué)公眾號(hào)后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~



          瀏覽 38
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)

          評(píng)論
          圖片
          表情
          推薦
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码一级 | 蜜桃在线视频 | 99久久婷婷 | 中文字幕综合在线观看 | 最新欧美国产 |