?
??一、面向物件和面向程序異同
??1、面向程序
- 面向程序的程式設計的核心是程序(流水線式思維),程序即解決問題的步驟,
- 面向程序的設計就好比精心設計好一條流水線,考慮周全什么時候處理什么東西,
- 優點是:極大的降低了寫程式的復雜度,只需要順著要執行的步驟,堆疊代碼即可,
- 缺點是:一套流水線或者流程就是用來解決一個問題,代碼牽一發而動全身,
- 應用場景:一旦完成基本很少改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等,
??2、面向物件
面向物件的程式設計的核心是物件(上帝式思維),要理解物件為何物,必須把自己當成上帝,上帝眼里世間存在的萬物皆為物件,不存在的也可以創造出來,
當下的程式員應該都聽過"面向物件編程"一詞,也經常有人問能不能用一句話解釋下什么是"面向物件編程",我們先來看看比較正式的說法,
"把一組資料結構和處理它們的方法組成物件(object),把相同行為的物件歸納為類(class),通過類的封裝(encapsulation)隱藏內部細節,通過繼承(inheritance)實作類的特化(specialization)和泛化(generalization),通過多型(polymorphism)實作基于物件型別的動態分派,"
- 優點:解決了程式的擴展性,對某一個物件單獨修改,會立刻反映到整個體系中,如對游戲中一個人物引數的特征和技能修改都很容易,
- 缺點:可控性差,無法向面向程序的程式設計流水線式的可以很精準的預測問題的處理流程與結果,面向物件的程式一旦開始就由物件之間的互動解決問題,即便是上帝也無法預測最終結果,于是我們經常看到一個游戲人某一引數的修改極有可能導致陰霸的技能出現,一刀砍死3個人,這個游戲就失去平衡,
- 應用場景:需求經常變化的軟體,一般需求的變化都集中在用戶層,互聯網應用,企業內部軟體,游戲等都是面向物件的程式設計大顯身手的好地方,
?
??二、類的相關知識
在講類之前需要了解一些名詞:類、物件、實體、實體化
- 類:具有相同特征的一類事物(人、狗、老虎)
- 物件/實體:具體的某一個事物比如小狗類中的旺財(特指某一條狗)
- 實體化:類——>物件的程序
?
??三、類的相關操作方法
??1、定義類
在Python中可以使用class關鍵字定義類,然后在類中通過之前學習過的函式來定義方法,這樣就可以將物件的動態特征描述出來,代碼如下所示,
比如創建一個Dog類,為即將創建的所有狗物件系結name和age兩個屬性,并且賦予每條創建的狗坐下( set() )的能力
class Dog:#創建一個狗類 role = 'dog' # 狗的角色屬性都是狗 # __init__是一個特殊方法用于在創建物件時進行初始化操作 # 通過這個方法我們可以為狗物件系結name和age兩個屬性 def __init__(self, name, age): self.name = name self.age = age def sit(self): '''模仿小狗接到命令(物件呼叫該函式)時坐下''' print('小狗已經坐下了')
??1.1、說明
寫在類中的函式,我們通常稱之為(物件的)方法,這些方法就是物件可以接收的訊息,
??2、創建和使用物件
??2.1、實體化一個物件
實體化類其他編程語言中一般用關鍵字 new,但是在 Python 中并沒有這個關鍵字,類的實體化類似函式呼叫方式, 以下使用類的名稱Dog來實體化,并通過 init 方法接收引數,
上面我們創建了一個狗類,但是要實體化一條實實在在的獨一無二的狗那該怎么操作呢?
實體化一只實實在在的旺財
wc = Dog('旺財' , 1) #創造了一只具體的狗(旺財)
??2.2、訪問屬性
您可以使用點號 . 來訪問物件的屬性,使用如下類的名稱訪問類變數
創建完了旺財,上面不是說了為即將創建的所有狗物件系結name和age兩個屬性,那我想查看我創建的旺財的屬性(name,age)該怎么辦呢?往下看
print(wc.name) print(wc.age) 輸出結果: 旺財 1
有人會說上面我們創建的Dog類賦予每條創建的狗坐下( set() )的能力,那么我家的旺財應該也有這種能力,那么就用以下方法使旺財展示這種能力
#使旺財坐下 wc.sit() 輸出結果: 小狗已經坐下了
??3、總結類與物件的關系
??3.1、類的總結
類與物件是整個面向物件中最基礎的組成單元,
類:是抽象的概念集合,表示的是一個共性的產物,類之中定義的是屬性和行為(方法);
物件:物件是一種個性的表示,表示一個獨立的個體,每個物件擁有自己獨立的屬性,依靠屬性來區分不同物件,
??3.2、類和物件的區別
類是物件的模板,物件是類的實體,類只有通過物件才可以使用,而在開發之中應該先產生類,之后再產生物件,類不能直接使用,物件是可以直接使用的,用通俗的話來說在python中,用變數表示特征,用函式表示技能,因而具有相同特征和技能的一類事物就是‘類’,物件是則是這一類事物中具體的一個(比如上面我創建的旺財是實體化了一條獨一無二的狗),
?
??四、類中一些規則解釋
??1、關于__init__函式與它的引數self
上面我是這樣創建一個Dog類的
class Dog:#創建一個狗類 role = 'dog' # 狗的角色屬性都是狗 # __init__是一個特殊方法用于在創建物件時進行初始化操作 # 通過這個方法我們可以為狗物件系結name和age兩個屬性 def __init__(self, name, age): self.name = name self.age = age def sit(self): '''模仿小狗接到命令(物件呼叫該函式)時坐下''' print('小狗已經坐下了')
我們可以發現類里面有這樣一個__init__函式,每次創建類的實體物件時, __init__函式就會自動被呼叫,無論它里面有什么樣的變數、計算,統統會自動呼叫,
理解__init__函式需要搞清楚以下三點:
- 1、帶有兩個下劃線開頭的函式是宣告該屬性為私有,不能在類地外部被使用或直接訪問
- 2、init函式(方法)支持帶引數的類的初始化 ,也可為宣告該類的屬性
- 3、init函式(方法)的第一個引數必須是 self(self為習慣用法,也可以用別的名字),后續引數則可 以自由指定,和定義函式沒有任何區別,
至于它的引數必須叫做self嗎?
在實體化時自動將物件/實體本身傳給__init__的第一個引數,你也可以給他起個別的名字,但是正常人都不會這么做,
??2、知識點拓展
??2.1、init()要點如下
- 1.名稱固定,必須為__init__()
- 2.第一個引數固定,必須為self,self指的就是剛剛創建好的示例物件,
- 3.建構式通常用來初始化示例屬性,如下代碼就是初始化示例屬性:
- 4.通過類名(引數串列),來呼叫建構式,呼叫后,將創建好的物件回傳給相應的變數,
- 5.init()方法:初始化創建好的物件,初始化指的是:"給實體屬性賦值"
- 6.new()方法:用于創建物件,但我們一般無需定義該方法,
?
??五、類屬性的補充
一:我們定義的類的屬性到底存到哪里了?有兩種方式查看 dir(類名):查出的是一個名字串列 類名.__dict__:查出的是一個字典,key為屬性名,value為屬性值 二:特殊的類屬性 類名.__name__# 類的名字(字串) 類名.__doc__# 類的檔案字串 類名.__base__# 類的第一個父類(在講繼承時會講) 類名.__bases__# 類所有父類構成的元組(在講繼承時會講) 類名.__dict__# 類的字典屬性 類名.__module__# 類定義所在的模塊 類名.__class__# 實體對應的類(僅新式類中)
??1、__slots__??
類中沒有??__slots__??屬性時,可以進行動態添加屬性
class Dog(object): def __init__(self, name, age): self.name = name self.age = age p = Dog('lucy', 18) p.city = '上海' print(p.city) # 上海
當類中有??__slots__???時,可以對屬性進行控制,只可以設定??__slots__??中的屬性,如果設定的屬性不在范圍內,會?報錯?,
class Dog(object): __slots__ = ('name', 'age', 'sex') def __init__(self, name, age): self.name = name self.age = age p = Dog('lucy', 18) p.sex = '男' p.city = '上海' # 報錯 print(p.sex) # 男
??2、??__doc__??
類的檔案資訊
class Person(object): """ 這是人的檔案資訊 """ __slots__ = ('name', 'age', 'sex') def __init__(self, name, age): self.name = name self.age = age p = Person('lucy', 18) print(p.__doc__) # 物件名.__doc__ print(Person.__doc__) # 類名.__doc__ 輸出結果: 這是人的檔案資訊 這是人的檔案資訊
??3、??__module__??
獲取物件所在的模塊
?test.py中的代碼如下:?class Person(object): __slots__ = ('name', 'age', 'sex') def __init__(self, name, age): self.name = name self.age = age ?demo.py中的代碼:? import test p = test.Person('lucy', 18) print(p.__module__) # test
??4、??__class__
??
獲取物件的類名(全稱??__main__.類名??)class Person(object): __slots__ = ('name', 'age', 'sex') def __init__(self, name, age): self.name = name self.age = age p = Person('lucy', 18) print(p.__class__) #<class '__main__.Person'> 輸出結果: <class '__main__.Person'>
??5、??__dict__??
以字典的形式,顯示物件所有的屬性
class Person(object): def __init__(self, name, age): self.name = name self.age = age p = Person('lucy', 18) print(p.__dict__) # {'name': 'lucy', 'age': 18} 輸出結果: {'name': 'lucy', 'age': 18}
??6、??__dir__()??
與??dir(物件名)??等價,查看一個物件支持的所有屬性和方法
class Person(object): __slots__ = ('name', 'age') def __init__(self, name, age): self.name = name self.age = age p = Person('lucy', 18) print(p.__dir__()) print(dir(p)) print(set(p.__dir__()) - set(dir(p)))
輸出結果
??7、??__setitem__??方法
不能直接把一個物件當做字典來使用
class Person(object): def __init__(self, name, age, city): self.name = name self.age = age self.city = city p = Person('張三', 18, '襄陽') # 我想把age修改成20,會報錯 p['age'] = 20 # [] 語法會呼叫物件的 __setitem__方法
利用??__setitem__??方法,可以進行修改和添加屬性
class Person(object): def __init__(self, name, age, city): self.name = name self.age = age self.city = city def __setitem__(self, key, value): self.__dict__[key] = value p = Person('張三', 18, '襄陽') p['age'] = 20 p['sex'] = '男' print(p.__dict__) # {'name': '張三', 'age': 20, 'city': '襄陽', 'sex': '男'} print(p.age) 輸出結果: {'name': '張三', 'age': 20, 'city': '襄陽', 'sex': '男'} 20
??8、??__getitem__??方法
getitem__的作用是什么呢?說白了就是類中一個特殊方法,類物件可以像字典物件那樣根據key取值(dict['key']),如類物件Object['key'],系統會自動呼叫__getitem__方法(所以你在看pytorch里面Dataloader的時候沒有發現主函式直接呼叫__getitem,原來是系統自動呼叫),然后回傳該方法定義return值,說到這里,有一點需要強調哦, 字典取值時key不存在,會拋出例外,而類物件的key是否存在,都會呼叫__getitem__方法并回傳其規定的值,下面進入實體,
class Person(object): def __init__(self, name, age, city): self.name = name self.age = age self.city = city def __getitem__(self, item): return self.__dict__[item] p = Person('張三', 18, '襄陽') print(p['name']) # 張三 輸出結果: 張三
??9、??__delitem__??方法
delitem(self,key):
這個方法在對物件的組成部分使用__del__陳述句的時候被呼叫,應洗掉與key相關聯的值,同樣,僅當物件可變的時候,才需要實作這個方法,
class Person(object): def __init__(self, name, age, city): self.name = name self.age = age self.city = city def __delitem__(self, key): print(f'洗掉的屬性{key}') p = Person('張三', 18, '襄陽') del p['city'] # 洗掉的屬性city 輸出結果: 洗掉的屬性city
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/537667.html
標籤:Python
下一篇:抽象類的子類化機制
