面向對象的詳細解讀

来源:https://www.cnblogs.com/bpf-1024/archive/2019/04/15/10708463.html
-Advertisement-
Play Games

面向對象的詳細解讀 一、基本概念 1. 面向過程 (1) 概念:以過程為中心的編程思想,就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。 (2) 優點:極大的降低了寫程式的複雜度,只需要順著要執行的步驟,堆疊代碼即可。因為程式的流程很清楚,按著模 ...


面向對象的詳細解讀

 

一、基本概念

1. 面向過程

(1) 概念:以過程為中心的編程思想,就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。

(2) 優點:極大的降低了寫程式的複雜度,只需要順著要執行的步驟,堆疊代碼即可。因為程式的流程很清楚,按著模塊與函數的方法可以很好的組織。

(3) 缺點:只能用來解決一個問題,代碼牽一發而動全身。

(4) 應用:用於基本很少改變的場景,著名的例子有Linux內核、git、以及Apache HTTP Server等。

 

2. 面向對象

(1) 概念:程式設計的核心是對象,面向對象的方法主要是把事物給對象化,對象包括屬性與方法。

(2) 優點:易維護、易復用、易擴展,由於面向對象有封裝、繼承、多態性的特性,可以設計出低耦合的系統,使系統更加靈活、更加易於維護。

(3) 缺點:可控性差,無法像面向過程的程式設計一樣可以精準的預測問題的處理流程與結果。

(4) 應用:需求經常變化的軟體,一般需求的變化都集中在用戶層,如互聯網應用、企業內部軟體以及游戲等。

 

二、面向對象中的名詞解析

1. 類:類就是一個模板,模板里可以包含多個函數,每個函數都能實現一些功能。

2. 對象:根據模板()創建的實例,通過這個實例(對象)可以執行類中的函數。

3. 屬性:類中所定義的變數

4. 方法:類中所定義的函數

5. 實例化:通過類創建對象的過程

6. 總結對象的抽象是類,類的具體化就是對象也可以說類的實例化是對象,對象是類的實例

  》》》實例說明——類與對象的創建

# -*- encoding:utf-8 -*-
''' 實例說明——類與對象的創建 '''

class ClassName:    #創建類,ClassName為類名
    Alary = 10000     #類的一個屬性
    def Fun1(self):   #方法1
        pass             #方法1的技能
    def Fun2(self):   #方法2
        pass             #方法2的技能

obj = ClassName()   #創建對象,obj為對象名

 

三、特征

1. 封裝

(1) 概念:封裝是將對象運行時所需的資源封裝在程式對象中。簡單來說,就是將內容封裝起來,以後再去調用被封裝的內容。

(2) 調用封裝的內容有2種方法

——通過對象直接調用

——通過self間接調用

  》》》實例說明——面向對象的特征:封裝

# -*- encoding:utf-8 -*-
''' 實例說明——面向對象的特征:封裝 '''

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def detail(self): #調用時對象名會傳給self參數,如最後一句
        print(self.name)
        print(self.age)

obj1 = Student('Jack',15)  #將'Jack'和15分別封裝到obj1的self的name和age屬性中
print(obj1.name)  #通過對象直接調用name屬性和age屬性
print(obj1.age)

obj2 = Student('Sahra',13) #將'Sahra'和13分別封裝到obj2的self的name和age屬性中
obj2.detail()     #通過self間接調用name屬性和age屬性

 

2. 繼承

(1) 概念繼承可以使得子類別具有父類別的各種屬性和方法,而不需要再次編寫相同的代碼。在令子類別繼承父類別的同時,可以重新定義某些屬性,並重寫某些方法,即覆蓋父類別的原有屬性和方法,使其獲得與父類別不同的功能。

(2) 多繼承

註:Python的類可以繼承多個類,而JavaC#則只能繼承一個類

Python的類如果繼承了多個類,那麼其尋找方法的方式有2

 

  • 當類為經典類時會按照深度優先方式查找

  • 當類為新式類時會按照廣度優先方式查找

 

  》》》實例說明——面向對象的特征:繼承

# -*- encoding:utf-8 -*-
''' 實例說明——面向對象的特征:繼承 '''

class Person(object):   #定義Person父類
    def talk(self):       #定義父類的方法
        print("Person can talk.")
class Chinese(Person):  #定義Person父類的一個子類,同時是Characters類的父類
    def talkC(Person):    #定義方法
        print("Chinese can talk Mandarin.")
class Characters(Chinese):  #定義Chinese父類的一個子類
    def people(self):         #定義方法
        print("Chinese are clever and diligent.")
class American(Person):   #定義Person父類的一個子類
    def talkA(self):       #定義方法
        print("American can talk English.")

C = Characters() #定義父類的子類的子類
A = American()   #定義父類的子類
C.talk()         #調用繼承Person類的方法
A.talkA()        #調用本身的方法
C.people()       #調用本身的方法

 

3. 多態

概念:多態指同一個實體同時具有多種形式,在賦值之後,不同的子類對象調用相同的父類方法,產生的執行結果不同。

  》》》實例說明——面向對象的特征:多態

 1 # -*- encoding:utf-8 -*-
 2 ''' 實例說明——面向對象的特征:多態 '''
 3 import abc
 4 
 5 class Animal(metaclass=abc.ABCMeta): #同一類事物:動物
 6 
 7     @abc.abstractmethod
 8     def talk(self):
 9         pass
10 
11 class People(Animal): #動物的形態之一:人
12     def talk(self):
13         print('say hello')
14 
15 class Dog(Animal):    #動物的形態之二:狗
16     def talk(self):
17         print('say wangwang')
18 
19 class Pig(Animal):    #動物的形態之三:豬
20     def talk(self):
21         print('say aoao')
22 
23 
24 peo = People() #創建People類的對象peo
25 dog = Dog()    #創建Dog類的對象dog
26 pig = Pig()    #創建Pig類的對象pig
27 peo.talk()     #分別使用各種的方法
28 dog.talk()
29 pig.talk()

 

四、類的成員

1. 簡介:類的成員包括欄位、方法和屬性。在所有成員中,只有欄位中的普通欄位保存於對象中,因此創建多少個對象在記憶體中就有幾個普通欄位;而其他成員都保存在類中,也只占用一份記憶體空間。

2. 欄位:包括普通欄位和靜態欄位,他們在定義和使用都有所區別,而最本質的區別是記憶體中保存的位置不同。

(1) 普通欄位保存在對象中

(2) 靜態欄位保存在類中

 

 

3. 方法:包括普通方法、靜態方法和類方法,三種方法在記憶體中都歸屬於類,區別在於調用方式不同。

(1) 公有方法

調用:可由對象名直接調用;如果通過類名來調用屬於對象的公有方法,需要顯式為該方法的self參數傳遞一個對象名,用來明確指定訪問哪個對象的數據成員。

特點:至少一個self參數執行普通方法時,自動將調用該方法的對象賦值給self。在此方法中可以訪問屬於類和對象的成員。

(2) 私有方法

調用:只能在屬於對象的方法中通過self調用或在外部通過Python支持的特殊方式來調用。在此方法中可以訪問屬於類和對象的成員。

(3) 靜態方法

調用:可以通過類名和對象名調用,但不能直接訪問屬於對象的成員,只能訪問屬於類的成員

特點:無預設參數

(4) 類方法

調用:可以通過類名和對象名調用,但不能直接訪問屬於對象的成員,只能訪問屬於類的成員

特點:至少一個cls參數執行類方法時,自動將調用該方法的類複製給cls。

 

4. 屬性:其實是普通方法的變種。

 

5. 類成員的修飾符下劃線

  xxx :公有成員,在任何地方都能訪問

  __xxx  or  ...__xxx:私有成員,只有類對象自己能訪問,子類對象不能直接訪問,但在對象外部可以通過對象名._類名__xxx”這樣的特殊方式來訪問。

  _xxx:受保護成員,不能用'from module import *'導入

  __xxx__:系統定義的特殊成員

註:Python中不存在嚴格意義上的私有成員

 

6. 類的特殊成員

(1) __init__:構造方法,通過類創建對象時,自動觸發執行

(2) __del__:析構方法,當對象在記憶體中被釋放時,自動觸發執行,此方法一般無需定義。

(3) 類的屬性

  dir(類名)查出的是一個名字列表

  類名.__dict__:查出的是一個字典,key為屬性名,value為屬性值

(4) 特殊的類屬性

  類名.__name__:類的名字(字元串)

  類名.__doc__:類的文檔字元串

  類名.__base__:類的第一個父類(在講繼承時會講)

  類名.__bases__:類所有父類構成的元組(在講繼承時會講)

  類名.__dict__:類的字典屬性

  類名.__module__:類定義所在的模塊

  類名.__class__:實例對應的類(僅新式類中)

 

7. 混入機制

(1) 概念:Python類型的動態性使得我們可以動態為自定義類及其對象增加新的屬性和行為,俗稱混入(mixin)機制。

(2)  》》》實例說明 —— 混入機制

 1 # -*- encoding:utf-8 -*-
 2 ''' 實例說明 —— 混入機制 '''
 3 import types
 4 class Car:                  #定義類
 5     price = 100000          #定義類屬性,屬於靜態欄位,只保存於類中
 6     def __init__(self, c):
 7         self.color = c      #定義實例屬性
 8 
 9 mycar = Car("Blue")             #實例化對象
10 print(mycar.color, Car.price)       #查看實例屬性和類屬性的值
11 Car.price = 1200                    #修改類屬性的值
12 Car.name = 'Roman'                  #動態增加類屬性,屬於靜態欄位,只保存於類中
13 mycar.color = "Red"                 #修改實例屬性的值
14 print(Car.price, Car.name, mycar.color)
15 
16 def setSpeed(self, s):
17     self.speed = s
18 
19 mycar.setSpeed = types.MethodType(setSpeed, mycar) #動態增加成員方法
20 mycar.setSpeed(50)                                 #調用成員方法
21 print(mycar.speed)
22 
23 ''' 利用特殊的類屬性查看類與對象的屬性與行為 '''
24 print("Car類的屬性與行為如下:\n",Car.__dict__)
25 print("mycar對象的屬性與行為如下:\n",mycar.__dict__)

 

 五、使用面向對象思想實現基本操作

1. 三維向量類

(1) 簡述:實現向量的加減法、向量與標量的乘除法。

(2) 代碼實現:

#  --coding: gb2312--
''' 三維向量 '''

class vector3:
    def __init__(self, x_ = 0, y_ = 0, z_ = 0): #構造函數
        self.x = x_
        self.y = y_
        self.z = z_

    def __add__(self, obj):      #重載+作為加號
        return vector3(self.x+obj.x, self.y+obj.y, self.z+obj.z)

    def __sub__(self, obj):      #重載-作為減號
        return vector3(self.x-obj.x, self.y-obj.y, self.z-obj.z)

    def __mul__(self,n):         #重載*作為點乘
        return vector3(self.x*n, self.y*n, self.z*n)

    def __truediv__(self, obj):  #重載/作為除法
        return vector3(self.x/n, self.y/n, self.z/n)

    def __str__(self):
        return str(self.x)+','+str(self.y)+','+str(self.z)

if __name__ == "__main__":
    n = int(input("請輸入一個標量:"))
    a,b,c = map(int,input("請輸入第一個向量:").split())
    v1 = vector3(a,b,c)
    a,b,c = map(int,input("請輸入第二個向量:").split())
    v2 = vector3(a,b,c)
    print("兩向量的加法:",v1 + v2)
    print("兩向量的減法:",v1 - v2)
    print("標量與向量的乘法:",v1 * n)
    print("標量與向量的除法:",v1 / n)

 

2. 英文字元串處理

 (1) 簡述:用戶輸入一段英文,得到這段英文中所以長度為3的單詞,並去除重覆的單詞。

 (2) 代碼實現:

方法一: 使用 jieba 庫

 1 # -*- encoding:utf-8 -*-
 2 ''' 將一段英文中長度為3的單詞輸出,並去掉重覆的單詞 '''
 3 
 4 import jieba
 5 class ProString:
 6     Str = ""
 7     Dict = {}
 8     Ls = []
 9     def __init__(self,string,length = 3): #初始化
10         self.string = string
11         self.length = length
12         
13     def SignalWord(self):        #去除重覆的單詞
14         self.words = jieba.lcut(self.string)   #jieba分詞
15         for _ in self.words:                   #與詞頻演算法相似
16             self.Dict[_] = self.Dict.get(_,0) + 1
17         del(self.Dict[' '])                 #刪除空格項
18         self.Ls = list(self.Dict.keys())    #字典類型轉化成列表類型
19         self.StubbenWord(self.Ls)
20 
21     def StubbenWord(self,Ls):       #利用去除重覆的單詞,得到固定長度的單詞
22         for _ in Ls:
23             if len(_) == self.length:
24                 self.Str += _ + ' '
25         self.printf(self.Str)
26         
27     def printf(self,Str):
28         print("處理後的字元串為:",Str)
29             
30 if __name__ == "__main__":
31     str = input("請輸入字元串:")
32     process = ProString(str,3)
33     process.SignalWord()

 

方法二: 使用 re庫 (正則表達式)

 1 # -*- encoding:utf-8 -*-
 2 ''' 將一段英文中長度為3的單詞輸出,並去掉重覆的單詞 '''
 3 
 4 import re
 5 class ProStr:
 6     a = []
 7     def __init__(self, words, length = 3):
 8         self.words = words
 9         self.length = length
10 
11     def process(self):
12         word_list = re.split('[\. ]+',self.words)
13         for _ in word_list:
14             if len(_) == self.length:
15                 if _ not in self.a:
16                     self.a.append(_)
17             else:
18                 continue
19         self.printf()
20 
21     def printf(self):
22         print("處理後的字元串為:", end = '')
23         for _ in range(len(self.a)):
24             print(self.a[_],end=' ')
25 
26 if __name__ == "__main__":
27     words = input("請輸入字元串:")
28     process = ProStr(words, 3)
29     process.process()

 

<拓展閱讀>

1. 定義類方法時一定要有self 參數嗎?

Python中,定義類的方法時將第一個參數定義為“self”只是一個習慣,而實際上類的方法中第一個參數的名字是可以變化的,而不一定要使用“self”這個名字但一般建議編寫代碼時仍以“self”作為方法的第一個參數名字。

 

2. 在python中,方法與函數有區別嗎?

:在Python中,函數和方法是有區別的。方法一般指與特定實例綁定的函數,通過對象調用方法時,對象本身將被作為第一個參數隱式傳遞過去,普通函數並不具備這個特點。

 

3. 類和對象在記憶體中如何保存?

:類以及類中的方法在記憶體中只占一份記憶體,而根據類創建的每一個對象在記憶體中都需要一份記憶體。如下圖:

 

   如上圖所示,根據類創建對象時,對象中除了封裝 name age 的值之外,還會保存一個類對象指針,該值指向當前對象的類。

  當通過 obj1 執行 【方法一】 時,過程如下:

  • 根據當前對象中的 類對象指針 找到類中的方法
  • 將對象 obj1 當作參數傳給 方法的第一個參數 self 

 

 4.  IDLE中下劃線’_’的奇葩用法

(1) 表示解釋器中最後一次顯示的內容或最後一語句正確執行的輸出結果

 

(2) 表示不關心變數的值

 

 

(3) 在對象、類名或模塊後面加上一個圓點 '.',稍等一秒鐘則會自動列出其所有公開成員。如果在圓點 '.' 後面再加一個下劃線 '_',則會列出其所有成員,包括私有成員。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • javascript中toFixed使用的是銀行家舍入規則。 銀行家舍入:所謂銀行家舍入法,其實質是一種四舍六入五取偶(又稱四舍六入五留雙)法。 簡單來說就是:四舍六入五考慮,五後非零就進一,五後為零看奇偶,五前為偶應捨去,五前為奇要進一。但是不論引入toFixed解決浮點數計算精度缺失的問題也好, ...
  • 瞭解JavaScript的同學可能知道,JavaScript語言由於設計原因,導致語言本身存在很多先天性的不足,當然這並非設計者有意的,js語言最初是被設計來作為網頁交互的腳本語言,依照現有的js語法來看,其最初的需求已經完全能夠滿足。互聯網的發展極大的提高了對web端的要求,不僅僅要求簡單的頁面交 ...
  • 1.什麼是XSS http://netsecurity.51cto.com/art/201610/518517.htm https://www.bilibili.com/video/av32599703 ...
  • 谷歌向上滾動滾輪是正值,向下是負值,而火狐正好相反 完整測試代碼,分別用谷歌和火狐瀏覽器測試 ...
  • 閑聊 步入前端切圖仔行列的我曾多次糾結過「到底使用哪種編輯器寫前端好用?」這樣的問題,前前後後嘗試過 Dreamweaver 、HBuilder 、Sublime Text 、Atom 和現在主要使用的 VSCode 。現在回過頭來看,我發現這個問題有了答案,那就是「愛用啥用啥」。(笑…… 今天的主 ...
  • request、out對象使用 一、實驗目的 1、掌握代碼片段中的註釋的應用; 2、掌握JSP腳本標示 Java代碼片段的應用。 二、實驗內容 1、設計教師與學生不同登陸界面,如下圖; 2、驗證碼隨機生成; 3、提交後分別轉向教師頁面和學生頁面進行判斷用戶名和密碼正確性; 4、如果正確,3秒後,轉向 ...
  • 渲染機制 渲染機制主要分為兩部分: 首次渲染和更新渲染。 首次渲染 首先通過一個小例子,來講解首次渲染過程。 程式運行到 時,其中的 babel React.createElement(ClickCounter, null) element`如下: 接下來執行 函數,生成 節點。首先瞭解下 的部分數 ...
  • 原文首發: "行為型模式:解釋器模式" 十一大行為型模式之十:解釋器模式。 簡介 姓名 :解釋器模式 英文名 :Interpreter Pattern 價值觀 :不懂解釋到你懂​ 個人介紹 : Given a language, define a representation for its gra ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...