python——面向對象

来源:https://www.cnblogs.com/Wu-Ling/archive/2022/07/29/16528922.html
-Advertisement-
Play Games

編程思想: 面向過程:問題比較簡單,可以用線性的思維解決 面向對象:問題較為複雜,使用簡單的線性思維無法解決 兩種編程思想都是解決問題的方式,並不對立,通過面向對象的方式便於我們從巨集觀上把握事物之間的複雜關係、便於我們分析整個系統。本質仍然使用面向過程的方式來處理。 面向對象的程式設計強調把數據和操 ...


編程思想:

  • 面向過程:問題比較簡單,可以用線性的思維解決
  • 面向對象:問題較為複雜,使用簡單的線性思維無法解決

  兩種編程思想都是解決問題的方式,並不對立,通過面向對象的方式便於我們從巨集觀上把握事物之間的複雜關係、便於我們分析整個系統。本質仍然使用面向過程的方式來處理

  面向對象的程式設計強調把數據和操作結合為一個不可分割的系統單位(即對象),對象的外部只需要知道它在做什麼,而不需要知道怎麼做。

類和對象:

類是抽象的模板,而實例是根據類創建出來的一個個具體的 ”對象“ ,每個對象都擁有相同的方法,但各自的數據可能不相同。

類:

  類是多個類似事物組成的群體的總稱。能夠幫助我們快速理解和判斷事物的性質。

1 class 類名( object ): # 類名有一個或多個單詞構成,每個單詞首字母大寫其餘小寫,用下劃線連接
2     pass

 

  Tip : object 表示該類是從哪個類繼承(後補充)下來的,通常,如果沒有合適的繼承類,就使用 object 類,這是所有類都會繼承的類。

數據類型:

  • 不同的數據類型屬於不同的類。
  • 可以使用  type()  函數來查看變數的數據類型。

對象:

   對象是類的具體實例(instance),python 中一切皆對象

   類是一種數據結構,類定義數據類型的數據(屬性 )和行為(方法)。對象是類的具體實體,也可以稱為類的實例。需要註意,類的實例和實例對象有時不那麼容易區分但又不是同一個東西。在在用class 關鍵字創建自定義的類對象的時,創建的是類的實例;而後者是用類對象創建實例對象。

  Python中一切皆對象;類定義完成後,會在當前作用域中定義一個以類名為名字,指向類對象的變數(名字)。

屬性:

Generally speaking, instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class:

 

類數據屬性:

  類屬性是某個類所有實例共用的屬性,在創建實例對象時,每個實例都會擁有類數據屬性的一個拷貝。

實例變數屬性:

  由類中__ init __() 方法定義的屬性(變數)。通過 “ . ”來訪問。在每個實例對象初始化時都會賦予獨有的數據。 

舉幾個慄子:

1 class Student:
2     
3     school = JXNU             # class variable shared by all instances
4     
5     def __init__(self, name):
6         self.name = name      # instance variable unique to each instance
 1 class Student:
 2     school = 'JXNU'
 3 
 4     def __init__(self, name):
 5         self.name = name
 6 
 7 
 8 stu1 = Student('Zhang')
 9 stu2 = Student('Li')
10 
11 print(stu1.school)    # =>JXNU
12 print(stu2.school)    # =>JXNU
13 
14 print('-'*20)
15 Student.school = 'SDJU'
16 print(stu1.school)    # =>SDNU
17 print(stu2.school)    # =>SDNU
18 
19 print('-'*20)
20 stu1.school = 'ZJNU'
21 print(stu2.school)    # =>SDNU
22 print(stu1.school)    # =>ZJNU
23 
24 print('-'*20)
25 Student.school = 'PJNU'
26 print(stu1.school)    # =>ZJNU
27 print(stu2.school)    # =>PJNU
  • 所有的實例初始化時都創建了一個指向同一個類屬性的指針。用類名Student修改類屬性school時,實例中的school也會發生改變。而用實例 stu1 修改對應的 school 時,指針將不指向原來的類屬性了,而是指向其他的變數。
  • 類 Student 中,類屬性 school 為所有實例共用;實例屬性 name 為每個 Student 的實例獨有。
  • 實例屬性是不能用類名訪問的屬性,必須由實例名 + ‘ . ' 來訪問。且每個實例對應一套。

私有屬性和公有屬性:

通常約定以兩個下劃線開頭而不以兩個下劃線結尾的變數為私有變數,其他的為公有變數。不能直接訪問私有變數,但可以在方法中訪問。

特殊屬性:

類屬性

含義

__name__

類的名字(字元串)

__doc__

類的文檔字元串

__bases__

類的所有父類組成的元組

__dict__

類的屬性組成的字典

__module__

類所屬的模塊

__class__

類對象的類型

方法:

實例方法:

一般需要傳遞 self 參數用於調用實例的實例屬性(變數),且只能由實例訪問。沒有矛盾和衝突點不做贅述。

類方法:

  • 用 @classmethod 修飾的方法,可以用類名直接訪問。第一個參數必須是當前類對象,該參數名一般約定為“cls”,通過它來傳遞類的屬性和方法(不能傳實例的屬性和方法)。
  • 原則上,類方法是將類本身作為對象進行操作的方法。假設有個方法,這個方法在邏輯上採用類本身作為對象來調用更合理,那麼這個方法就可以定義為類方法。另外,如果需要繼承,也可以定義為類方法。

 

靜態方法:

  • 用 @staticmethod 修飾的方法,可以用類名直接訪問。第一個參數必須是當前類對象,該參數名一般約定為“cls”,通過它來傳遞類的屬性和方法(不能傳實例的屬性和方法)。
  • 靜態方法是類中的函數,不需要實例。靜態方法主要是用來存放邏輯性的代碼,邏輯上屬於類,但是和類本身沒有關係,也就是說在靜態方法中,不會涉及到類中的屬性和方法的操作。可以理解為,靜態方法是個獨立的、單純的函數,它僅僅托管於某個類的名稱空間中,便於使用和維護。
  • 靜態方法更像是可以寫在類外的函數,但這樣是為了在邏輯上與類保持一定聯繫,不破壞類的邏輯性。

  類方法和靜態方法的用途有時會混淆。

舉幾個慄子:

  * 類方法慄子

 1 情景:
 2 假設我有一個學生類和一個班級類,想要實現的功能為:
 3     執行班級人數增加的操作、獲得班級的總人數;
 4     學生類繼承自班級類,每實例化一個學生,班級人數都能增加;
 5     最後,我想定義一些學生,獲得班級中的總人數。
 6 
 7 class ClassTest(object):
 8     __num = 0
 9 
10     @classmethod
11     def addNum(cls):
12         cls.__num += 1
13 
14     @classmethod
15     def getNum(cls):
16         return cls.__num
17 
18     # 這裡我用到魔術方法__new__,主要是為了在創建實例的時候調用累加方法。
19     def __new__(self):
20         ClassTest.addNum()
21         return super(ClassTest, self).__new__(self)
22 
23 
24 class Student(ClassTest):
25     def __init__(self):
26         self.name = ''
27 
28 a = Student()
29 b = Student()
30 print(ClassTest.getNum())

  * 靜態方法慄子

 1 import time
 2 
 3 class TimeTest(object):
 4     def __init__(self, hour, minute, second):
 5         self.hour = hour
 6         self.minute = minute
 7         self.second = second
 8 
 9     @staticmethod
10     def showTime():
11         return time.strftime("%H:%M:%S", time.localtime())
12 
13 
14 print(TimeTest.showTime())
15 t = TimeTest(2, 10, 10)
16 nowTime = t.showTime()
17 print(nowTime)

 

實例屬性和方法的動態綁定:

話不多說,直接上代碼:

 1 class Student:
 2     def __init__(self, name):
 3         self.name = name
 4 
 5 
 6 stu1 = Student('Zhang')
 7 stu2 = Student('Li')
 8 
 9 stu1.age = 20
10 print(stu1.age)    # =>20
11 print(stu2.age)    # AttributeError: 'Student' object has no attribute 'age'
12 
13 ### 追加的屬性或者方法只屬於這一實例不能用於共用。 ###

 

面向對象的三大特征:

封裝:

  • 將數據(屬性)和方法打包到類對象中。在方法內部對屬性進行操作,在類對象的外部調用方法。這樣就無需關心方法內部的複雜實現,從而將實現和使用相分離。由類和對象來實現。
  • 調用封裝內容可以直接用類名也可以創建一個類的實例。

繼承:

  • 提高代碼的復用性。
  • 將多個類共有的方法提取到父類中,子類僅需繼承父類而不必一一實現每個
     1 class 父類(object):
     2     def 父類中的方法(self):
     3         # doing sth
     4 
     5 
     6 class 子類(父類):   # 子類繼承父類,即繼承了父類中的所有方法
     7     pass
     8 
     9 
    10 zi = 子類()         # 創建子類的實例對象
    11 
    12 zi.父類中的方法()    # 執行從父類中繼承的方法

     

  • 不同於Java、C++,Python允許多繼承。類繼承了多個類時尋找方法的方式有兩種,分別是深度優先廣度優先。經典類多繼承是會按深度優先搜索方法;新式類則是按廣度優先搜索。這樣區分經典類和新式類呢?從字面上可以看出一個老一個新,新的必然包含了跟多的功能,也是之後推薦的寫法,從寫法上區分的話,如果當前類或者父類繼承了object類,那麼該類便是新式類,否則便是經典類。搜索有先後順序,所以不會產生多個同名方法的衝突。

多態:

  •  Pyhon不支持Java和C#這一類強類型語言中多態的寫法,但是原生多態,Python 本身就是一種多態語言。Python崇尚“鴨子類型”(duck typing)。

在程式設計中,鴨子類型(英語:duck typing)是動態類型的一種風格。在這種風格中,一個對象有效的語義,不是由繼承自特定的類或實現特定的介面,而是由當前方法和屬性的集合決定。這個概念的名字來源於由James Whitcomb Riley提出的鴨子測試,“鴨子測試”可以這樣表述:

    “當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。”

在鴨子類型中,關註的不是對象的類型本身,而是它是如何使用的。例如,在不使用鴨子類型的語言中,我們可以編寫一個函數,它接受一個類型為鴨的對象,並調用它的走和叫方法。在使用鴨子類型的語言中,這樣的一個函數可以接受一個任意類型的對象,並調用它的走和叫方法。如果這些需要被調用的方法不存在,那麼將引發一個運行時錯誤。任何擁有這樣的正確的走和叫方法的對象都可被函數接受的這種行為引出了以上表述,這種決定類型的方式因此得名。

鴨子類型通常得益於不測試方法和函數中參數的類型,而是依賴文檔、清晰的代碼和測試來確保正確使用。從靜態類型語言轉向動態類型語言的用戶通常試圖添加一些靜態的(在運行之前的)類型檢查,從而影響了鴨子類型的益處和可伸縮性,並約束了語言的動態特性。

 1 class F1:
 2     pass
 3 
 4 
 5 class S1(F1):
 6 
 7     def show(self):
 8         print 'S1.show'
 9 
10 
11 class S2(F1):
12 
13     def show(self):
14         print 'S2.show'
15 
16 def Func(obj):
17     print obj.show()
18 
19 s1_obj = S1()
20 Func(s1_obj) 
21 
22 s2_obj = S2()
23 Func(s2_obj) 
24 
25 ### Python “鴨子類型” ###

 

小結:

  • 面向對象是一種編程方式,此編程方式的實現是基於對  和 對象 的使用
  • 類 是一個模板,模板中包裝了多個“函數”供使用
  • 對象,根據模板創建的實例(即:對象),實例用於調用被包裝在類中的函數
  • 面向對象三大特性:封裝、繼承和多態

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

-Advertisement-
Play Games
更多相關文章
  • 寫在前面 本系列的文章是博主邊學邊記錄的,可能不是特別的正確,因為會加上博主自己的理解,僅供參考。 正文: 為了能夠將用戶程式裝入記憶體,必須為它分配一定大小的記憶體空間。常見的分配方式有: 1.連續分配 連續分配方式是最早出現的一種存儲器分配方式,該分配方式為一個用戶程式分配一個連續的記憶體空間。常見的 ...
  • 文本編輯工具VIM 1.vi/vim介紹 我們要學會如何去新建文件、刪除文件、修改文件等等,那麼做這些操作就需要一個文本編輯工具。而在linux中最經典最流行的文本編輯工具就是vi/vim,當然也有一些其他的文本編輯工具。 例如 emacs pico nano joe jed 諸如此類,但我們只需要 ...
  • SiteSucker for Mac是一款運行在Mac平臺上的整站下載工具,在SiteSucker Mac版中輸入網址就能離線下載一個網站里的所有內容,包括HTML、圖片、CSS 樣式表、JS 文件、Flash 文件等,SiteSucker for mac版的操作十分簡單,非常的實用。 詳情:Sit ...
  • 1.軟體下載 [root@localhost ~]# cd /usr/src/ [root@localhost src]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.38-linux-glibc2.12-x86 ...
  • 20 | 幻讀是什麼,幻讀有什麼問題? 建表和初始化語句如下 CREATE TABLE `t` ( `id` int(11) NOT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY ` ...
  • 業務端需要求連續90日每日的用戶留存率改怎麼計算呢??? 一: 本文采用MySQL8.0環境 1: 建表數據 CREATE TABLE `user_login` ( `user_id` int NOT NULL, `login_date` varchar(20) CHARACTER SET utf8 ...
  • 我們已經介紹瞭如何在 Kubernetes 和 KubeSphere 上部署 RadonDB MySQL 集群。本文將演示如何在 Rancher[1] 上部署 RadonDB MySQL Kubernetes 2.2.0[2],快速獲得一套 MySQL 容器化集群。 部署準備 已部署 Rancher ...
  • --創建用戶① --GRANT(授權)REVOKE(回收許可權)--創建用戶create user 用戶名 identified by 密碼 GRANT CONNECT,RESOURCE TO 用戶;GRANT CREATE VIEW TO 用戶;GRANT CREATE SYNONYM TO 用戶; ...
一周排行
    -Advertisement-
    Play Games
  • WPF本身不支持直接的3D繪圖,但是它提供了一些用於實現3D效果的高級技術。 如果你想要在WPF中進行3D繪圖,你可以使用兩種主要的方法: WPF 3D:這是一種在WPF應用程式中創建3D圖形的方式。WPF 3D提供了一些基本的3D形狀(如立方體、球體和錐體)以及一些用於控制3D場景和對象的工具(如 ...
  • 一、XML概述 XML(可擴展標記語言)是一種用於描述數據的標記語言,旨在提供一種通用的方式來傳輸和存儲數據,特別是Web應用程式中經常使用的數據。XML並不預定義標記。因此,XML更加靈活,並且可以適用於廣泛的應用領域。 XML文檔由元素(element)、屬性(attribute)和內容(con ...
  • 從今年(2023)三月份開始,Github開始強制用戶開啟兩步驗證2FA(雙因數)登錄驗證,毫無疑問,是出於安全層面的考慮,畢竟Github賬號一旦被盜,所有代碼倉庫都會毀於一旦,關於雙因數登錄的必要性請參見:別讓你的伺服器(vps)淪為肉雞(ssh暴力破解),密鑰驗證、雙向因數登錄值得擁有。 雙因 ...
  • 第一題 下列代碼輸入什麼? public class Test { public static Test t1 = new Test(); { System.out.println("blockA"); } static { System.out.println("blockB"); } publi ...
  • 本文主要涉及的問題:用ElementTree和XPath讀寫XML文件;解決ElementTree新增元素後再寫入格式不統一的問題;QTableWidget單元格設置控制項 ...
  • QStandardItemModel 類作為標準模型,主打“類型通用”,前一篇水文中,老周還沒提到樹形結構的列表,本篇咱們就好好探討一下這貨。 還是老辦法,咱們先做示例,然後再聊知識點。下麵這個例子,使用 QTreeView 組件來顯示數據,使用的列表模型比較簡單,只有一列。 #include <Q ...
  • 一、直充內充(充值方式) 直充: 包裝套餐直接充值到上游API系統。【PID/Smart】 (如:支付寶、微信 話費/流量/語音/簡訊 等 充值系統)。 內充(套餐打包常見物聯卡系統功能): 套餐包裝 適用於不同類型套餐 如 流量、簡訊、語音 等。 (目前已完善流量邏輯) 二、套餐與計費產品 計費產 ...
  • 在前面幾天中,我們學習了Dart基礎語法、可迭代集合,它們是Flutter應用研發的基本功。今天,我們繼續學習Flutter應用另一個必須掌握知識點:非同步編程(即Future和async/await)。它類似於Java中的FutureTask、JavaScript中的Promise。它是後續Flut... ...
  • 針對改動範圍大、影響面廣的需求,我通常會問上線了最壞情況是什麼?應急預案是什麼?你帶開關了嗎?。當然開關也是有成本的,接下來本篇跟大家一起交流下高頻發佈支撐下的功能開關技術理論與實踐結合的點點滴滴。 ...
  • 1.d3.shuffle D3.shuffle() 方法用於將數組中的元素隨機排序。它使用 Fisher–Yates 洗牌演算法,該演算法是無偏的,具有最佳的漸近性能(線性時間和常數記憶體)。 D3.shuffle() 方法的語法如下: d3.shuffle(array, [start, end]) 其中 ...