python面向對象編程的基本概念

做者|HIMANSHI SINGH
編譯|VK
來源|Analytics Vidhyajava

介紹

在學習面向對象編程時,我決定深刻研究它的歷史,結果發現它很迷人。術語「面向對象編程」(OOP)是Alan Kay 在1966年研究生院時提出的。python

Simula語言是第一種具備面向對象編程特色的編程語言。它是在1967年開發的,用於製做模擬程序,其中最重要的信息稱爲對象。數據庫

儘管OOPS自20世紀60年代初就在市場上,但在20世紀90年代,OOPS開始由於C++而增加。編程

除此以外,這種編程技術已經被包括Python在內的各類編程語言所採用,它的應用幾乎遍佈全部領域,如實時系統、人工智能、專家系統、CS系統、面向對象數據庫等等。數組

所以,在本文中,我將解釋Python中面向對象編程的基本概念。安全

目錄

  1. 什麼是面向對象編程?數據結構

  2. 面向對象編程(OOP)與面向過程編程(POP)機器學習

  3. OOPs的主要概念編程語言

    1. 什麼是類?
    2. 對象和對象實例化
    3. 類方法
    4. Python類中的繼承
    5. 封裝
    6. 多態性
    7. 數據抽象

什麼是面向對象編程?

面向對象編程(OOP)就是建立「對象」。對象是一組相互關聯的變量和函數。這些變量一般稱爲對象的屬性,函數稱爲對象的行爲。這些對象爲程序提供了一個更好、更清晰的結構。函數

例如,汽車能夠是一個對象。若是咱們把汽車看成一個對象,那麼它的屬性就是——顏色、型號、價格、品牌等等,它的行爲/函數是加速、減速、換擋。

另外一個例子——若是咱們把狗看成一個物體,那麼它的屬性就是——它的顏色、品種、名字、體重等,而它的行爲/函數是行走、吠叫、玩耍等。

面向對象編程因其在編程中實現了對象、隱藏、繼承等現實實體而聞名。它使可視化更容易,由於它接近真實世界的場景。

面向對象編程(OOP)與面向過程編程(POP)

OOP和過程式編程的基本區別是

  • 一種思考POP的方法就是你作檸檬水的方式。製做檸檬水的過程包括——首先根據須要取水,而後在水中加入糖,而後在混合物中加入檸檬汁,最後將整個溶液混合。這樣你的檸檬水就準備好了。一樣,POP也須要必定的步驟。程序程序由函數組成。這意味着在POP方法中,程序被劃分爲特定於不一樣任務的函數。這些功能按特定的順序排列,程序的控制按順序進行。

  • 而OOP程序是由對象組成的。面向對象方法將程序劃分爲對象。這些對象是將現實世界對象的屬性和行爲捆綁在一塊兒的實體。

  • POP只適用於小任務。由於隨着程序長度的增長,代碼的複雜性也隨之增長。最後變成了一個函數網。並且,它變得很難調試。OOP經過更清晰、以更不復雜的結構來解決這個問題。它容許以繼承的形式從新使用代碼。

  • 另外一個重要的是,在面向過程的編程中,全部函數均可以訪問全部數據,這意味着缺少安全性。假設你想保護來自世界各地的憑據或任何其餘關鍵信息。那麼程序化方法就不能爲你提供這種安全性。由於這個OOP幫助你實現了一個稱爲封裝的驚人功能,它容許咱們隱藏數據。不用擔憂,在本文的後半部分,我將詳細介紹這一點以及面向對象編程的其餘概念。如今,只需理解OOP支持安全性,POP不支持。

  • 編程語言如C、Pascal和Basic使用過程方法,而java、Python、JavaScript、PHP、Scala和C++是提供面向對象方法的主要語言。

OOPs的主要概念

在本節中,咱們將深刻探討OOP的基本概念。咱們將討論如下主題

  1. 對象

  2. 方法

  3. 繼承

  4. 封裝

  5. 多態性

  6. 數據抽象

1.什麼是類?

這個問題的直接答案是:類是對象的集合。與原始數據結構不一樣,類是用戶定義的數據結構。它們使代碼更易於管理。

讓咱們看看如何定義下面的類

class class_name:
    class body

咱們用關鍵字「class」在類名和分號後面定義一個類。在使用縮進以後,咱們會考慮有縮進的全部東西。爲了讓這更容易理解,讓咱們看一個例子。

以汽車展廳爲例。你要存儲每輛車的詳細信息。讓咱們首先定義一個類

class Car:
    pass

就這樣!

注意:我用pass語句代替了它的主體,由於主要目的是展現如何定義一個類,而不是它應該包含什麼。

在詳細介紹以前,首先要了解對象和實例化。

2.對象和對象實例化

當咱們定義一個類時,只會建立對象的描述或藍圖,在這個過程當中沒有內存分配。而對象實例具備內存分配,它包含真實的數據或信息。

實例化是建立一個類的實例。讓咱們建立上面定義的類的對象-

obj1 = Car()

這樣就建立了一個對象實例。請注意,你能夠根據你的選擇更改對象名稱。

嘗試打印此對象

print(obj1)

由於咱們的類是空的,因此它返回存儲對象的地址,即0x7fc5e677b6d8

在繼續學習以前,你還須要瞭解類的構造函數。

類構造函數

到目前爲止,咱們有一輛空的車,是時候把車的特徵填滿咱們的類了。類構造函數的工做是在建立類的對象時將值分配給類的數據成員。

一輛車能夠有不一樣的屬性,如名稱、顏色、型號、品牌、發動機功率、重量、價格等。咱們將僅選擇其中幾項以便於理解。

class Car:
    def __init__(self, name, color):
        self.name = name
        self.color = color

所以,car或任何其餘對象的屬性必須位於一個咱們稱爲 __init__( )的方法中。此方法也稱爲構造函數方法。每當類的對象被構造時,就調用構造函數方法。

如今,讓咱們來討論一下 __init__( )方法的參數。因此,這個方法的第一個參數必須是self。而後纔是剩下的參數

構造函數方法中的兩個語句是

  1. self.name = name
  2. self.color = color:

這將建立新的屬性,即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。

3.類方法

到目前爲止,咱們已經添加了汽車的屬性。如今是時候添加一些行爲了。方法是咱們用來描述對象行爲的函數。它們也在類中定義。請看下面的代碼

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()。

  • 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()方法有一個附加參數,所以咱們在調用它時傳遞了一個參數。

注意:三件重要的事要記住

  1. 能夠建立一個類的任意數量的對象。

  2. 若是方法須要n個參數,而你沒有傳遞相同數量的參數,則會發生錯誤。

  3. 參數的順序很重要。

讓咱們一個個來看看

  1. 建立一個類的多個對象
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))

  1. 參數數目錯誤
class Car:

    def __init__(self, name, mileage):
        self.name = name 
        self.mileage = mileage
Honda = Car("Honda City")
print(Honda)

由於咱們沒有提供第二個參數,因此咱們獲得了這個錯誤。

  1. 參數順序
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,瞭解全部這些很是重要。到目前爲止,咱們已經介紹了面向對象編程的基本知識,讓咱們進一步深刻。

4. Python類中的繼承

繼承是一個類繼承另外一個類的屬性和方法的過程。被繼承的類稱爲父類。從父類繼承屬性的類是子類。

有趣的是,除了繼承的屬性和方法外,子類能夠有本身的屬性和方法。

如何繼承父類?使用如下語法:

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類的單獨方法。

5.封裝

正如我在文章開頭部分提到的,封裝是確保安全性的一種方法。基本上,它將數據隱藏起來,不讓外人訪問。例如,若是咱們想讓某些值不被客戶或任何未經受權的人訪問,那麼封裝就是確保這一點的方法。

你能夠在方法或屬性的名稱前使用一個下劃線( _ ) 來聲明受保護的方法或屬性。例如 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)      #名稱修飾

請注意,這個規則的設計是想處理某些狀況,例如在調試器中。可是正常編程中不推薦使用

6.多態

多態(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類的函數。

7.數據抽象

咱們使用抽象來隱藏函數的內部細節或實現,只顯示其功能。這與你在不知道汽車原理的狀況下知道如何駕駛汽車,或者你知道如何用開關打開或關閉燈,但你不知道插座後面發生了什麼的狀況相似。

任何具備至少一個抽象函數的類都是抽象類。爲了首先建立一個抽象類,你須要從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/

相關文章
相關標籤/搜索