做者|HIMANSHI SINGH
編譯|VK
來源|Analytics Vidhyajava
在學習面向對象編程時,我決定深刻研究它的歷史,結果發現它很迷人。術語「面向對象編程」(OOP)是Alan Kay 在1966年研究生院時提出的。python
Simula語言是第一種具備面向對象編程特色的編程語言。它是在1967年開發的,用於製做模擬程序,其中最重要的信息稱爲對象。數據庫
儘管OOPS自20世紀60年代初就在市場上,但在20世紀90年代,OOPS開始由於C++而增加。編程
除此以外,這種編程技術已經被包括Python在內的各類編程語言所採用,它的應用幾乎遍佈全部領域,如實時系統、人工智能、專家系統、CS系統、面向對象數據庫等等。數組
所以,在本文中,我將解釋Python中面向對象編程的基本概念。安全
什麼是面向對象編程?數據結構
面向對象編程(OOP)與面向過程編程(POP)機器學習
OOPs的主要概念編程語言
面向對象編程(OOP)就是建立「對象」。對象是一組相互關聯的變量和函數。這些變量一般稱爲對象的屬性,函數稱爲對象的行爲。這些對象爲程序提供了一個更好、更清晰的結構。函數
例如,汽車能夠是一個對象。若是咱們把汽車看成一個對象,那麼它的屬性就是——顏色、型號、價格、品牌等等,它的行爲/函數是加速、減速、換擋。
另外一個例子——若是咱們把狗看成一個物體,那麼它的屬性就是——它的顏色、品種、名字、體重等,而它的行爲/函數是行走、吠叫、玩耍等。
面向對象編程因其在編程中實現了對象、隱藏、繼承等現實實體而聞名。它使可視化更容易,由於它接近真實世界的場景。
OOP和過程式編程的基本區別是
一種思考POP的方法就是你作檸檬水的方式。製做檸檬水的過程包括——首先根據須要取水,而後在水中加入糖,而後在混合物中加入檸檬汁,最後將整個溶液混合。這樣你的檸檬水就準備好了。一樣,POP也須要必定的步驟。程序程序由函數組成。這意味着在POP方法中,程序被劃分爲特定於不一樣任務的函數。這些功能按特定的順序排列,程序的控制按順序進行。
而OOP程序是由對象組成的。面向對象方法將程序劃分爲對象。這些對象是將現實世界對象的屬性和行爲捆綁在一塊兒的實體。
POP只適用於小任務。由於隨着程序長度的增長,代碼的複雜性也隨之增長。最後變成了一個函數網。並且,它變得很難調試。OOP經過更清晰、以更不復雜的結構來解決這個問題。它容許以繼承的形式從新使用代碼。
另外一個重要的是,在面向過程的編程中,全部函數均可以訪問全部數據,這意味着缺少安全性。假設你想保護來自世界各地的憑據或任何其餘關鍵信息。那麼程序化方法就不能爲你提供這種安全性。由於這個OOP幫助你實現了一個稱爲封裝的驚人功能,它容許咱們隱藏數據。不用擔憂,在本文的後半部分,我將詳細介紹這一點以及面向對象編程的其餘概念。如今,只需理解OOP支持安全性,POP不支持。
編程語言如C、Pascal和Basic使用過程方法,而java、Python、JavaScript、PHP、Scala和C++是提供面向對象方法的主要語言。
在本節中,咱們將深刻探討OOP的基本概念。咱們將討論如下主題
類
對象
方法
繼承
封裝
多態性
數據抽象
這個問題的直接答案是:類是對象的集合。與原始數據結構不一樣,類是用戶定義的數據結構。它們使代碼更易於管理。
讓咱們看看如何定義下面的類
class class_name: class body
咱們用關鍵字「class」在類名和分號後面定義一個類。在使用縮進以後,咱們會考慮有縮進的全部東西。爲了讓這更容易理解,讓咱們看一個例子。
以汽車展廳爲例。你要存儲每輛車的詳細信息。讓咱們首先定義一個類
class Car: pass
就這樣!
注意:我用pass語句代替了它的主體,由於主要目的是展現如何定義一個類,而不是它應該包含什麼。
在詳細介紹以前,首先要了解對象和實例化。
當咱們定義一個類時,只會建立對象的描述或藍圖,在這個過程當中沒有內存分配。而對象實例具備內存分配,它包含真實的數據或信息。
實例化是建立一個類的實例。讓咱們建立上面定義的類的對象-
obj1 = Car()
這樣就建立了一個對象實例。請注意,你能夠根據你的選擇更改對象名稱。
嘗試打印此對象
print(obj1)
由於咱們的類是空的,因此它返回存儲對象的地址,即0x7fc5e677b6d8
在繼續學習以前,你還須要瞭解類的構造函數。
到目前爲止,咱們有一輛空的車,是時候把車的特徵填滿咱們的類了。類構造函數的工做是在建立類的對象時將值分配給類的數據成員。
一輛車能夠有不一樣的屬性,如名稱、顏色、型號、品牌、發動機功率、重量、價格等。咱們將僅選擇其中幾項以便於理解。
class Car: def __init__(self, name, color): self.name = name self.color = color
所以,car或任何其餘對象的屬性必須位於一個咱們稱爲 __init__( )的方法中。此方法也稱爲構造函數方法。每當類的對象被構造時,就調用構造函數方法。
如今,讓咱們來討論一下 __init__( )方法的參數。因此,這個方法的第一個參數必須是self。而後纔是剩下的參數
構造函數方法中的兩個語句是
這將建立新的屬性,即name和color,而後將參數的值分配給它們。「self」關鍵字表示類的實例。經過使用「self」關鍵字,咱們能夠訪問類的屬性和方法。它在方法定義和變量初始化中頗有用。「self」在每次定義方法時都顯式使用。
注意:你也能夠在此方法以外建立屬性。可是這些屬性對整個類都是通用的,必須給它們賦值。
假設你的展廳中的全部汽車都是Sedan,而不是一次又一次地指定它,你能夠經過建立一個屬性來將car_type的值固定爲Sedan。
class Car: car_type = "Sedan" #類屬性 def __init__(self, name, color): self.name = name #實例屬性 self.color = color #實例屬性
這裏,實例屬性是指構造函數方法中的屬性,在這個例子中是self.name 和 self.color。類屬性是指構造函數方法以外的屬性,在這個例子中是car_type。
到目前爲止,咱們已經添加了汽車的屬性。如今是時候添加一些行爲了。方法是咱們用來描述對象行爲的函數。它們也在類中定義。請看下面的代碼
class Car: car_type = "Sedan" def __init__(self, name, mileage): self.name = name self.mileage = mileage def description(self): return f"The {self.name} car gives the mileage of {self.mileage}km/l" def max_speed(self, speed): return f"The {self.name} runs at the maximum speed of {speed}km/hr"
在類中定義的方法(而不是構造函數方法)稱爲實例方法。此外,這裏有兩個實例方法,description()和max_speed()。
請注意,附加參數speed沒有使用「self」關鍵字。由於speed不是一個實例變量,因此咱們不使用self關鍵字做爲前綴。讓咱們爲上面描述的類建立一個對象。
obj2 = Car("Honda City",24.1) print(obj2.description()) print(obj2.max_speed(150))
咱們所作的是建立一個類car的對象並傳遞所需的參數。爲了使用object_name.method_name().
description()方法沒有任何附加參數,所以在調用它時沒有傳遞任何參數。
max_speed()方法有一個附加參數,所以咱們在調用它時傳遞了一個參數。
注意:三件重要的事要記住
能夠建立一個類的任意數量的對象。
若是方法須要n個參數,而你沒有傳遞相同數量的參數,則會發生錯誤。
參數的順序很重要。
讓咱們一個個來看看
class Car: def __init__(self, name, mileage): self.name = name self.mileage = mileage def max_speed(self, speed): return f"The {self.name} runs at the maximum speed of {speed}km/hr"
Honda = Car("Honda City",21.4) print(Honda.max_speed(150)) Skoda = Car("Skoda Octavia",13) print(Skoda.max_speed(210))
class Car: def __init__(self, name, mileage): self.name = name self.mileage = mileage
Honda = Car("Honda City") print(Honda)
由於咱們沒有提供第二個參數,因此咱們獲得了這個錯誤。
class Car: def __init__(self, name, mileage): self.name = name self.mileage = mileage def description(self): return f"The {self.name} car gives the mileage of {self.mileage}km/l"
Honda = Car(24.1,"Honda City") print(Honda.description())
搞混了!由於咱們改變了論點的順序。
如今,面向對象編程有四個基本概念:繼承、封裝、多態和數據抽象。爲了理解OOPs,瞭解全部這些很是重要。到目前爲止,咱們已經介紹了面向對象編程的基本知識,讓咱們進一步深刻。
繼承是一個類繼承另外一個類的屬性和方法的過程。被繼承的類稱爲父類。從父類繼承屬性的類是子類。
有趣的是,除了繼承的屬性和方法外,子類能夠有本身的屬性和方法。
如何繼承父類?使用如下語法:
class parent_class: body of parent class class child_class( parent_class): body of child class
讓咱們看看實現
class Car: #父類 def __init__(self, name, mileage): self.name = name self.mileage = mileage def description(self): return f"The {self.name} car gives the mileage of {self.mileage}km/l" class BMW(Car): #子類 pass class Audi(Car): #子類 def audi_desc(self): return "This is the description method of class Audi."
obj1 = BMW("BMW 7-series",39.53) print(obj1.description()) obj2 = Audi("Audi A8 L",14) print(obj2.description()) print(obj2.audi_desc())
咱們建立了兩個子類,即「BMW」和「Audi」,它們繼承了父類「Car」的方法和屬性。在BMW類咱們沒有提供額外的特徵和函數。而Audi內部的一個附加方法。
注意在obj1.description()和obj2.description()的幫助下,父類的實例方法description()是如何被子類的對象訪問的。此外,還可使用obj2.Audi_desc()訪問Audi類的單獨方法。
正如我在文章開頭部分提到的,封裝是確保安全性的一種方法。基本上,它將數據隱藏起來,不讓外人訪問。例如,若是咱們想讓某些值不被客戶或任何未經受權的人訪問,那麼封裝就是確保這一點的方法。
你能夠在方法或屬性的名稱前使用一個下劃線( _ ) 來聲明受保護的方法或屬性。例如 self._name或def _method();這兩行都說明屬性和方法是受保護的,不該在類和子類的訪問以外使用,而是能夠由類方法和對象訪問。
Python只是將‘_‘ 用做編碼約定,告訴你應該在類的範圍內使用這些屬性/方法。你仍然能夠像往常同樣訪問定義爲受保護的變量和方法。
如今,爲了實際防止從類範圍以外訪問屬性/方法,可使用「私有成員」。若要將屬性/方法聲明爲私有成員,請在前綴中使用雙下劃線( __ ) 。例如– self.__name或def __method();這兩行都說明屬性和方法是私有的,不能從類外部進行訪問。
class car: def __init__(self, name, mileage): self._name = name #受保護屬性 self.mileage = mileage def description(self): return f"The {self._name} car gives the mileage of {self.mileage}km/l"
obj = car("BMW 7-series",39.53) #經過類方法訪問受保護變量 print(obj.description()) #直接從外部訪問受保護變量 print(obj._name) print(obj.mileage)
請注意咱們如何訪問受保護的變量而沒有任何錯誤。很明顯,對變量的訪問仍然是公開的。讓咱們看看封裝是如何工做的
class Car: def __init__(self, name, mileage): self.__name = name #私有變量 self.mileage = mileage def description(self): return f"The {self.__name} car gives the mileage of {self.mileage}km/l"
obj = Car("BMW 7-series",39.53) #經過類方法訪問私有變量 print(obj.description()) #直接從外部訪問私有變量 print(obj.mileage) print(obj.__name)
當咱們嘗試使用description()方法訪問私有變量時,沒有遇到任何錯誤。可是當咱們嘗試直接在類外部訪問私有變量時,Python給出了一個錯誤,聲明:car對象沒有屬性''__name'。
你仍然可使用該屬性的修飾名稱直接訪問它。Name mangling(命名修飾)是一種從外部訪問類成員的機制。Python解釋器將任何帶有「__var」的標識符重寫爲「_ClassName__var」。使用這個你能夠從外部訪問類成員。
class Car: def __init__(self, name, mileage): self.__name = name #私有變量 self.mileage = mileage def description(self): return f"The {self.__name} car gives the mileage of {self.mileage}km/l"
obj = Car("BMW 7-series",39.53) #經過類方法訪問私有變量 print(obj.description()) #直接從外部訪問私有變量 print(obj.mileage) print(obj._car__name) #名稱修飾
請注意,這個規則的設計是想處理某些狀況,例如在調試器中。可是正常編程中不推薦使用
多態(Polymorphism)一個希臘單詞。若是咱們分解Polymorphism這一術語,咱們會獲得「poly」(多)和「morph」(變形)形式。因此多態性意味着有多種形式。在OOP中,它指的是具備相同名稱但具備不一樣功能的函數。
class Audi: def description(self): print("This the description function of class AUDI.") class BMW: def description(self): print("This the description function of class BMW.")
audi = Audi() bmw = BMW() for car in (audi,bmw): car.description()
使用對象audi調用函數時,將調用audi類的函數;使用對象bmw調用函數時,將調用bmw類的函數。
咱們使用抽象來隱藏函數的內部細節或實現,只顯示其功能。這與你在不知道汽車原理的狀況下知道如何駕駛汽車,或者你知道如何用開關打開或關閉燈,但你不知道插座後面發生了什麼的狀況相似。
任何具備至少一個抽象函數的類都是抽象類。爲了首先建立一個抽象類,你須要從ABC模塊導入ABC類。這使你能夠在其中建立抽象方法。ABC表明抽象基類。
from abc import ABC class abs_class(ABC): Body of the class
重要的是,不能爲抽象類建立實例對象。例如-
from abc import ABC, abstractmethod class Car(ABC): def __init__(self,name): self.name = name @abstractmethod def price(self,x): pass
obj = Car("Honda City")
如今的問題是咱們如何準確地使用這個抽象。答案是使用繼承。
from abc import ABC, abstractmethod class Car(ABC): def __init__(self,name): self.name = name def description(self): print("This the description function of class car.") @abstractmethod def price(self,x): pass class new(Car): def price(self,x): print(f"The {self.name}'s price is {x} lakhs.")
obj = new("Honda City") obj.description() obj.price(25)
Car是從ABC模塊的ABC類繼承的抽象類。注意我在抽象類中有一個抽象方法(price())和一個具體方法(description())。這是由於抽象類能夠同時包含這兩種類型的函數,而普通類則不能。從這個抽象類繼承的另外一個類是new。new的price()方法是咱們重寫了抽象類Car的price方法。
在用戶從new()類建立對象並調用price()方法以後,new()類中price方法的定義就開始發揮做用了。這些定義對用戶是隱藏的。抽象方法只是提供一個聲明。須要提供子類的定義。
可是,當爲new()類(即obj)的對象調用description()方法時,將調用Car的description()方法,由於它不是抽象方法。
總之,在本文中,我介紹了Python中面向對象編程的基本概念。如今大家知道OOPs和基本概念了。
原文連接:https://www.analyticsvidhya.com/blog/2020/09/object-oriented-programming/
歡迎關注磐創AI博客站:
http://panchuang.net/
sklearn機器學習中文官方文檔:
http://sklearn123.com/
歡迎關注磐創博客資源彙總站:
http://docs.panchuang.net/