面向对象:编程范式、类、对象
編程范式:
1. 面向過程編程: 核心是“過程”,“過程”指的是解決問題的步驟;就相當于在設(shè)計一條流水線
? ? 優(yōu)點:復雜問題流程化,進而簡單化
缺點:可擴展性差,前一發(fā)動全身
2. 面向?qū)ο?#xff1a;核心是“對象”,對象就是特征與技能的結(jié)合體
優(yōu)點: 可擴展性強
? ? 缺點: 編程復雜度高
應(yīng)用場景: 用戶需求經(jīng)常變化,如:互聯(lián)網(wǎng)應(yīng)用、游戲、企業(yè)內(nèi)部應(yīng)用
類:?
類就是一系列對象相似的特征與技能的結(jié)合體(相當于一個模板),特征用變量表示,技能用函數(shù)表示
強調(diào): 站在不同的角度,得到的分類是不一樣的
在程序中: 一定是先定義類,后調(diào)用類產(chǎn)生對象?
定義類、產(chǎn)生對象的方法如下:
"""定義類""" class Student: # 類的首字母大寫school = "Luffycity" def learn(self): print("is learning")def eat(self):print("is eating")def sleep(self):print("is sleeping")"""調(diào)用類產(chǎn)生對象""" stu1 = Student() # Student() 不是執(zhí)行類體的代碼,而是得到一個返回值,這個返回值就是產(chǎn)生的對象;這個過程也叫“實例化” stu2 = Student() # 類名調(diào)用一次就是實例化一次 stu3 = Student()print(stu1) print(stu2) print(stu3)# 輸出結(jié)果: # <__main__.Student object at 0x0000001F205C6438> # <__main__.Student object at 0x0000001F205C66D8> # <__main__.Student object at 0x0000001F205C6668>?
類的使用:
定義類時,在類定義階段它內(nèi)部的代碼就能夠運行,如下:
class Student: # 類的首字母大寫school = "Luffycity" # 特征print("test")def learn(self): # 技能print("is learning")def eat(self):print("is eating")def sleep(self):print("is sleeping")# 運行結(jié)果: # test查看類里面的名稱空間:
class Student: # 類的首字母大寫school = "Luffycity" # 類的數(shù)據(jù)屬性def learn(self): # 類的函數(shù)屬性print("is learning")def eat(self):print("is eating")def sleep(self):print("is sleeping")print(Student.__dict__) print(Student.__dict__["school"]) print(Student.__dict__["learn"])"""查看""" print(Student.school) print(Student.learn)"""類定義完后增加屬性""" Student.country = "China" # 往Student這個類里面增加了 country = "China" print(Student.__dict__) print(Student.country)"""刪除""" del Student.country print(Student.__dict__)"""修改""" Student.country = "Greater China" print(Student.country)# 打印結(jié)果: # {'__module__': '__main__', 'school': 'Luffycity', 'learn': <function Student.learn at 0x000000711C26B9D8>, 'eat': <function Student.eat at 0x000000711C26BA60>, 'sleep': <function Student.sleep at 0x000000711C26BD90>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None} # Luffycity # <function Student.learn at 0x000000711C26B9D8> # Luffycity # <function Student.learn at 0x000000711C26B9D8> # {'__module__': '__main__', 'school': 'Luffycity', 'learn': <function Student.learn at 0x000000711C26B9D8>, 'eat': <function Student.eat at 0x000000711C26BA60>, 'sleep': <function Student.sleep at 0x000000711C26BD90>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'country': 'China'} # China # {'__module__': '__main__', 'school': 'Luffycity', 'learn': <function Student.learn at 0x000000711C26B9D8>, 'eat': <function Student.eat at 0x000000711C26BA60>, 'sleep': <function Student.sleep at 0x000000711C26BD90>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None} # Greater China
?
類內(nèi)部定義的變量是類的數(shù)據(jù)屬性 ,定義的函數(shù)是其函數(shù)屬性
類的用途:
1. 對屬性的操作
2. 實例化產(chǎn)生一個個對象 (利用? Student() 方法)
?
對象的使用方法:
利用 init 方法來為對象定制自己獨有的特征
class Student:school = "Luffycity"def __init__(self,name,gender,age): # 實例化的時候就會自動調(diào)用 __init__函數(shù)self.Name = nameself.Gender = genderself.Age = age # 字典形式"""stu1.Name = "蒼老師"stu1.Gender = "女"stu1.Age = 18"""def learn(self):print("is learning")def eat(self):print("is eating")def sleep(self):print("is sleeping")stu1 = Student("蒼老師","女",18)stu2 = Student("武藤蘭","男",38)""" 有__init__函數(shù)時的實例化步驟: 1. 先產(chǎn)生一個空對象stu1(不帶自己獨特屬性的對象) 2. 觸發(fā)__init__函數(shù),觸發(fā)方式為:Student.__init__() , 這是一個函數(shù),就需要按照函數(shù)的方式進行傳參,即: Student.__init__(stu1,name,gender,age) (第一步生成的對象stu1傳入self的位置)Student.__init__(stu1,name,gender,age) 產(chǎn)生的效果如__init__函數(shù)中的注釋所示。 (添加獨有屬性后,對象的內(nèi)存地址不變)
3. 返回 帶自己獨特屬性的對象stu1 """""" stu1 = Student("蒼老師","女",18) 這是在給一個對象定制一個屬性,與類添加屬性一個道理,往對象里面添加屬性也涉及到名稱空間的變動,只不過這個名稱空間是stu1的名稱空間(因為是往stu1這個對象里面添加的新屬性) """ print(stu1.__dict__) # 打印結(jié)果: # {'Name': '蒼老師', 'Gender': '女', 'Age': 18}""" 通過__init__的方法, stu1這個對象不但擁有類共有的那些特征和技能,并且也有了自己獨有的屬性""""""查看""" print(stu1.Name) print(stu1.Gender) # 打印結(jié)果: # 蒼老師 # 女"""改""" stu1.Name = "蒼井空" print(stu1.__dict__) print(stu1.Name) # 打印結(jié)果: # {'Name': '蒼井空', 'Gender': '女', 'Age': 18} # 蒼井空"""增加""" stu1.job = "adult video" print(stu1.__dict__) print(stu1.job) # 打印結(jié)果: # {'Name': '蒼井空', 'Gender': '女', 'Age': 18, 'job': 'adult video'} # adult video"""刪除""" del stu1.job print(stu1.__dict__) # 打印結(jié)果: # {'Name': '蒼井空', 'Gender': '女', 'Age': 18}
類中的數(shù)據(jù)屬性是所有對象共有的;
類中的函數(shù)屬性:是綁定給對象使用的,而且綁定到不同的對象是不同的綁定方法
還以上面的代碼為例:
print(Student.school,id(Student.school)) print(stu1.school,id(stu1.school))# 打印結(jié)果: # Luffycity 586247585648 # Luffycity 586247585648"""類中的數(shù)據(jù)屬性是所有對象共有的,用的都是同一塊內(nèi)存地址""""""類中的函數(shù)屬性:是綁定給對象,而且綁定到不同的對象是不同的綁定方法"""
print(Student.learn)
print(stu1.learn)
print(stu2.learn)
# 打印結(jié)果: (函數(shù)的內(nèi)存地址也不一樣)
# <function Student.learn at 0x0000005FB155BA60> # 類名.功能名 是一個函數(shù)的內(nèi)存地址,就是一個函數(shù),那就按函數(shù)的方法去執(zhí)行,而且函數(shù)不會自動傳參的
# <bound method Student.learn of <__main__.Student object at 0x0000005FB15667B8>> # 對象.功能名是一種綁定方法,所以能夠自動傳參
# <bound method Student.learn of <__main__.Student object at 0x0000005FB15667F0>> # 功能跟不同對象的綁定方法不一樣 ?
?
把上述例子中類的代碼稍微修改,如下:
class Student:school = "Luffycity"def __init__(self, name, gender, age): # 實例化的時候就會自動調(diào)用 __init__函數(shù)self.Name = nameself.Gender = genderself.Age = age # 字典形式def learn(self):print("%s is learning" % self.Name)def eat(self):print("%s is eating" % self.Name)def sleep(self):print("%s is sleeping" % self.Name)stu1 = Student("蒼老師", "女", 18) stu2 = Student("武藤蘭","男",38)?
調(diào)用 Student.learn() 函數(shù)的方法:(此函數(shù)需傳入?yún)?shù))
Student.learn(stu1) # Student.learn()就是一個普通的函數(shù),所以可以利用函數(shù)的調(diào)用方式去執(zhí)行它;函數(shù)的參數(shù)要傳入上一步產(chǎn)生的stu1, 因為在類中定義learn()函數(shù)時,里面有參數(shù)self# 執(zhí)行結(jié)果: # 蒼老師 is learning?
調(diào)用stu1.learn()函數(shù)的方法: (此函數(shù)無需傳入?yún)?shù),因為learn功能只需傳入?yún)?shù)self,而stu1會自動傳入self)
"""調(diào)用stu1.learn()函數(shù)""" stu1.learn() # 這個函數(shù)調(diào)用的是類Student下的learn的功能,stu1會作為參數(shù)自動傳入到self這個形參中# 執(zhí)行結(jié)果: # 蒼老師 is learning?
即: 類中的函數(shù)屬性是綁定給對象使用的,綁定到不同的對象是不同的綁定方法,對象調(diào)用綁定方式時,會把對象本身當做第一個參數(shù),傳入self
類中定義的功能(即 函數(shù))是給對象使用的(綁定給對象使用的),而且是哪個對象來調(diào)用就把哪個對象作為參數(shù)自動傳入到self中(這是 綁定關(guān)系),這樣 哪個對象在調(diào)用就是哪個對象在執(zhí)行類中的功能;類如果自己使用還需要自己傳入對象(傳入到self中),會比較笨拙
對象只存放自己獨有的特征,相似的特征都放在類里面;這涉及到對象的屬性查找問題,如果對象中的屬性跟類中的屬性重名,則以對象中的屬性為準(類似于函數(shù)中變量的先局部后全局)(例外,屬性不會去全局里面找,因為你是在調(diào)用類,或者說這是類的調(diào)用)
"""有重名""" stu1.x = "CN" Student.x = "中國"print(stu1.x) print(Student.x)# 打印結(jié)果: # CN # 中國"""無重名時,對象調(diào)用類中的""" Student.x = "中國"print(stu1.x) print(Student.x)# 打印結(jié)果: # 中國 # 中國補充說明1:
1. 站在不同角度,定義出的類是不同的
2. 現(xiàn)實中的類并不完全等同于程序中的類,比如現(xiàn)實中的公司類,在程序中有時需拆分成部門類、業(yè)務(wù)類等
3. 有時為了變成需求,程序中可能會定義現(xiàn)實中不存在的類,比如策略類,現(xiàn)實中不存在,但在程序中是一個很常見的類
補充說明2:
Python中一切皆對象,并且在Python3中統(tǒng)一了類與類型的概念?
class Student:school = "Luffycity"def __init__(self, name, gender, age): # 實例化的時候就會自動調(diào)用 __init__函數(shù)self.Name = nameself.Gender = genderself.Age = age # 字典形式def learn(self):print("%s is learning" % self.Name)def eat(self):print("%s is eating" % self.Name)def sleep(self):print("%s is sleeping" % self.Name)print(type([1,2])) print(list) # [1,2] 和 list是Python中的列表這個數(shù)據(jù)類型 print(Student) # Student 是我們自己創(chuàng)建的類# 打印結(jié)果: # <class 'list'> # <class 'list'> # <class '__main__.Student'>""" Python3中統(tǒng)一了類與類型的概念 """# 站在類的角度考慮下面已學過的知識 list1 = [1,2,3] # 這種方法的本質(zhì)是 list1 = list([1,2,3]) 即 調(diào)用list這個類并傳入?yún)?shù)[1,2,3],進而產(chǎn)生list1這個對象,并且[1,2,3]放入到了list1的命名空間中; list1中獨有的特征就是[1,2,3] list2 = [] # 同理, list2 = list() list1.append(4) # 這行代碼的含義是:list1這個對象調(diào)用了list這個類下面的 append() 這個功能(函數(shù))。 print(list1) """ list1.append(4) 其實就相當于 list.append(list1,4) 即 list這個類調(diào)用其內(nèi)部的append()函數(shù),并把list1這個對象傳入到self這個形參中 """ list.append(list1,5) print(list1)# 打印結(jié)果: # [1, 2, 3, 4] # [1, 2, 3, 4, 5] list2.append(1) # list2.append(1) : 添加的1只能添加到list2中,不會添加到list1中,因為是list2這個對象在調(diào)用append(1)這個功能 print(list2)# 打印結(jié)果: # [1]"""所以,在Python中一切皆對象"""?
可擴展性:
使用類可以將數(shù)據(jù)與專門操作該數(shù)據(jù)的功能捆綁在一起
?
例題1:
編寫一個學生類,產(chǎn)生多個學生對象
要求: 有一個計數(shù)器(屬性),統(tǒng)計總共實例化了多少個對象
代碼如下:
class Student:school = "luffycity"count = 0def __init__(self,name,gender,age):self.name = nameself.gender = genderself.age = age# self.count += 1 # 這種方式是不可行的,因為每次添加count時都添加到了對象的特有屬性里面,再產(chǎn)生下一個對象時,新產(chǎn)生的對象并不知道上一個對象count的值是多少;而且由于 __init__ 里面沒有對 count 這個變量賦值,所以 self.count 會向類的公共屬性里面去尋找count 的值"""正確寫法"""Student.count += 1 # 在 __init__函數(shù)里面對類Student的公共屬性count進行處理;count變量并沒有添加到對象命名空間中(沒有添加到對象的獨有屬性中),count一直都是在類Student的命名空間里def learn(self):print("%s is learning" %self.name)""" 分析要求: 每次實例化都會觸發(fā) __init__ 函數(shù),所以可以考慮在 __init__ 上進行計數(shù) 首先在類的公共屬性上添加一個 count = 0 """ stu1 = Student("neo","male",18) stu2 = Student("蒼老師","female",16) stu3 = Student("美奈子","female",17)print(stu1.count) # 此時的 stu1.count 調(diào)用的是類 Student中的變量count,stu1中是沒有count這個變量的 print(stu2.count) print(stu3.count) print(stu1.__dict__) print(stu2.__dict__) print(stu3.__dict__)print(Student.count)# 打印結(jié)果: # 3 # 3 # 3 # {'name': 'neo', 'gender': 'male', 'age': 18} # {'name': '蒼老師', 'gender': 'female', 'age': 16} # {'name': '美奈子', 'gender': 'female', 'age': 17} # 3?例題二:
模仿LOL定義兩個英雄類
要求:
英雄需要有昵稱、攻擊力、生命值等屬性
實例化出兩個英雄對象
英雄之間可以互毆,被打的一方掉血,血量小于0則判定為死亡
以下是自己寫的:(只定義了一個英雄類)
class Hero:def __init__(self,name,attack,life):self.name = nameself.attack = attackself.life = lifedef fighted(self,attacked = 0):self.life -= attackedif self.life <= 0:print("%s is dead" %self.name)else:print("%s is alive" %self.name)kasaa = Hero("卡薩丁",1000,2000) kayle = Hero("凱爾",1300,1500)kayle.fighted(kasaa.attack) kayle.fighted(kasaa.attack)?
示例代碼:
class Garen:camp = "Demacia"def __init__(self,nickname,attack,life):self.nickname = nicknameself.attack = attackself.life = lifedef attacking(self,enemy):enemy.life -= self.attackclass Riven:camp = "Noxus"def __init__(self,nickname,attack,life):self.nickname = nicknameself.attack = attackself.life = lifedef attacking(self,enemy):enemy.life -= self.attackgaren = Garen("草叢倫",30,100) riven = Riven("瑞雯雯",50,80)print(riven.life) garen.attacking(riven) # 英雄(對象)之間的交互 print(riven.life)# 運行結(jié)果 # 80 # 50?
上述代碼中有大量重復的代碼,利用“繼承”來解決。(轉(zhuǎn)下篇文章)
?
轉(zhuǎn)載于:https://www.cnblogs.com/neozheng/p/8479922.html
總結(jié)
以上是生活随笔為你收集整理的面向对象:编程范式、类、对象的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QQ计数器统计器使用教程
- 下一篇: 7-17 古风排版