類 : 具備相同屬性和技能的一類事物git
對象: 就是對一個類的具體的描述編程
實例化:類——>對象的過程函數
使用面向對象的好處:工具
結構上, 面向對象能夠分爲兩部分:屬性和方法ui
屬性又叫靜態屬性、靜態字段、靜態變量編碼
方法又叫動態屬性、函數spa
class A: name = 'hello' #靜態屬性、靜態字段、靜態變量 def fun(self): #動態屬性、方法、函數 pass
新建一個類,類名的首字母最好是大寫的,規範一點,不然Pycharm有波浪號code
類的屬性有兩種方式查看orm
dir(類名):查出的是一個名字列表對象
類名.__dict__:查出的是一個字典,key爲屬性名,value爲屬性值
class Person: 靜態變量 = 123 print(Person.__dict__) #內置的雙下劃線方法 執行輸出: {'__doc__': None, '靜態變量': 123, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__dict__': <attribute '__dict__' of 'Person' objects>} 從結果中,能夠找到 '靜態變量': 123
特殊的類屬性
類名.__name__ # 類的名字(字符串) 類名.__doc__ # 類的文檔字符串 類名.__base__ # 類的第一個父類(在講繼承時會講) 類名.__bases__ # 類全部父類構成的元組(在講繼承時會講) 類名.__dict__ # 類的字典屬性 類名.__module__ # 類定義所在的模塊 類名.__class__ # 實例對應的類(僅新式類中)
類名.__dict__['靜態變量名'] 能夠查看,可是不能刪改 類名.靜態變量名 直接就能夠訪問,能夠刪改 del 類名.靜態變量名 刪除一個靜態變量
類名.方法名 查看這個方法的內存地址
類名.方法名(實參) 調用了這個方法,必須傳一個實參,這個實參傳給了self
class Person: 靜態變量 = 123 #靜態屬性,靜態變量 role = 'person' def f1(self): #默認帶一個參數self,方法,動態屬性 print(1234567) #引用動態變量 Person.f1() # 執行報錯:TypeError: f1() missing 1 required positional argument: 'self' # 提示缺乏一個參數self 隨便傳一個參數,再次執行 Person.f1(1)
只要是類的方法,必需要傳self。self的名字,是約定俗成
產生一個實例(對象)的過程:對象 = 類名()
實例化對象的過程有幾步:
初始化方法,功能就是給對象self封裝屬性
class Person: role = 'person' #靜態屬性 def __init__(self,name,sex,hp,ad): self.name = name self.sex = sex self.hp = hp self.ad = ad summer = Person('summer','M',1,5) print(summer.__dict__)
廣義上的屬性,是指對象的屬性
在類裏面的def 通常叫方法。沒有順序之分,通常把init放到第一個.
class Person: role = 'person' #靜態屬性 def __init__(self,name,sex,hp,ad): self.name = name self.sex = sex self.hp = hp self.ad = ad def attack(self): print('{}發起了一次攻擊'.format(self.name)) summer = Person('ss','M',1,5) # 執行類方法,下面2種方法效果等同 Person.attack(summer) # attack是和Person關聯起來的,因此外部能夠直接調用attack方法 summer.attack() ''' 執行輸出: ss發起了一次攻擊 ss發起了一次攻擊 '''
方法的調用 :
1.類名.方法名(對象名) 方法中的self參數就指向這個對象
2.對象名.方法名() 這樣寫至關於方法中的self參數直接指向這個對象,推薦使用
① 查看類中全部的屬性和方法:__dict__。雖然__dict__也能查看類中某一個屬性,可是一般用來查看類中的全部屬性和方法,不作其餘用途
② 增刪改查類中的屬性:用萬能的點(類中沒有該屬性就增,有該屬性就改)
③ 操做類中的方法:通常不經過類名(通常經過對象名)
類名操做靜態屬性
(1)查看類中的全部內容:類名.__dict__方式
class Human: mind = '有思想' # 第一部分:靜態屬性 屬性 靜態變量 靜態字段 dic = {} l1 = [] def work(self): # 第二部分:方法 函數 動態屬性 print('人類會工做') print(Human.__dict__) print(Human.__dict__['mind']) Human.__dict__['mind'] = '無腦' # 報錯
經過.__dict__這種方式只能查詢,不能增刪改.。第一種方式只用戶查詢所有內容(通常不用單獨屬性查詢).
(2)經過萬能的點 能夠增刪改查類中的單個屬性
class Human: mind = '有思想' def work(self): # 第二部分:方法 函數 動態屬性 print('人類會工做') Human.walk = '直立行走' # 增 del Human.mind # 刪 Human.mind = '無腦' # 改 print(Human.mind) # 查
對以上兩種作一個總結:
類名操做動態方法
除了兩個特殊方法:靜態方法,類方法以外,通常不會經過類名操做一個類中的方法。
class Human: mind = '有思想' # 第一部分:靜態屬性 屬性 靜態變量 靜態字段 def work(self): # 第二部分:方法 函數 動態屬性 print('人類會工做') def tools(self): print('人類會使用工具') Human.work(111) Human.tools(111) # 下面能夠作,但不用。 Human.__dict__['work'](111)
實例化一個對象總共發生了三件事:
對象操做對象空間
(1)對象查詢對象中全部屬性 對象.__dict__
class Human: mind = '有思想' language = '實用語言' def __init__(self,name,sex,age,hobby): # self 和 obj 指向的是同一個內存地址同一個空間,下面就是經過self給這個對象空間封裝四個屬性。 self.n = name self.s = sex self.a = age self.h = hobby obj = Human('barry','男',18,'運動') print(obj.__dict__) # {'n': 'barry', 'h': '運動', 's': '男', 'a': 18}
(2)對象操做對象中的單個屬性 萬能的點 .
class Human: mind = '有思想' language = '實用語言' def __init__(self,name,sex,age,hobby): # self 和 obj 指向的是同一個內存地址同一個空間,下面就是經過self給這個對象空間封裝四個屬性。 self.n = name self.s = sex self.a = age self.h = hobby obj = Human('barry','男',18,'運動') obj.job = 'IT' # 增 del obj.n # 刪 obj.s = '女' # 改 print(obj.s) # 查
(3)對象查看類中的屬性
class Human: mind = '有思想' language = '實用語言' def __init__(self,name,sex,age,hobby): self.n = name self.s = sex self.a = age self.h = hobby obj = Human('barry','男',18,'運動') print(obj.mind) # 有思想 print(obj.language) # 實用語言
(4)對象操做類中的方法
class Human: mind = '有思想' language = '實用語言' def __init__(self,name,sex,age,hobby): self.n = name self.s = sex self.a = age self.h = hobby def work(self): print(self) print('人類會工做') def tools(self): print('人類會使用工具') obj = Human('barry','男',18,'運動') obj.work() obj.tools() ''' 執行輸出: <__main__.Human object at 0x000001576C1808C8> 人類會工做 人類會使用工具 '''
一個類能夠實例化多個對象
class Human: mind = '有思想' language = '實用語言' def __init__(self,name,sex,age,hobby): self.n = name self.s = sex self.a = age self.h = hobby def work(self): print(self) print('人類會工做') def tools(self): print('人類會使用工具') obj1= Human('李易峯','男',20,'拍戲') obj2= Human('趙麗穎','女',18,'唱歌') print(obj1,obj2) print(obj1.__dict__) print(obj2.__dict__) ''' 執行輸出: <__main__.Human object at 0x00000223534C0D88> <__main__.Human object at 0x00000223534C68C8> {'n': '李易峯', 's': '男', 'a': 20, 'h': '拍戲'} {'n': '趙麗穎', 's': '女', 'a': 18, 'h': '唱歌'} '''
練習:在終端輸出以下信息
小明,10歲,男,上山去砍柴
小明,10歲,男,開車去東北
小明,10歲,男,最愛大保健
老李,90歲,男,上山去砍柴
老李,90歲,男,開車去東北
老李,90歲,男,最愛大保健
老張…
class Person(object): def __init__(self, name, age, sex='男', hobby=('上山去砍柴', '開車去東北', '最愛大保健')): self.name = name self.age = age self.sex = sex self.hobby = hobby def info(self): for i in self.hobby: print('{},{}歲,{},{}'.format(self.name, self.age, self.sex, i)) ming = Person('小明', 10) li = Person('老李', 90) ming.info() li.info()
擴展題:使用面向對象的方式編碼三級菜單
將以前的代碼複製粘貼過來,切割成面向對象方式
# -*- coding: utf-8 -*- class AreaMenu(object): def __init__(self): self.zone = { '山東': { '青島': ['四方', '黃島', '嶗山', '李滄', '城陽'], '濟南': ['歷城', '槐蔭', '高新', '長青', '章丘'], '煙臺': ['龍口', '萊山', '牟平', '蓬萊', '招遠'] }, '江蘇': { '蘇州': ['滄浪', '相城', '平江', '吳中', '崑山'], '南京': ['白下', '秦淮', '浦口', '棲霞', '江寧'], '無錫': ['崇安', '南長', '北塘', '錫山', '江陰'] }, '浙江': { '杭州': ['西湖', '江干', '下城', '上城', '濱江'], '寧波': ['海曙', '江東', '江北', '鎮海', '餘姚'], '溫州': ['鹿城', '龍灣', '樂清', '瑞安', '永嘉'] } } self.province = list(self.zone.keys()) self.run() def run(self): # 省列表 while True: print('省'.center(20, '*')) for i in self.province: # 打印省列表 print('{}\t{}'.format(self.province.index(i) + 1, i)) province_input = input('請輸入省編號,或輸入q/Q退出:').strip() if province_input.isdigit(): province_input = int(province_input) if 0 < province_input <= len(self.province): province_id = province_input - 1 # 省編號,因爲顯示加1,獲取的時候,須要減1 city = list(self.zone[self.province[province_id]].keys()) # 城市列表 self.city(province_id, city) # 進入市區列表 else: print("\033[41;1m省編號 {} 不存在!\033[0m".format(province_input)) elif province_input.upper() == 'Q': break else: print("\033[41;1m輸入省編號非法!\033[0m") def city(self, province_id, city): # 市區列表 if province_id == '' or city == '': return 'province_id 和 city 參數不能爲空' while True: print('市'.center(20, '*')) for j in city: print('{}\t{}'.format(city.index(j) + 1, j)) city_input = input("請輸入市編號,或輸入b(back)返回上級菜單,或輸入q(quit)退出:").strip() if city_input.isdigit(): city_input = int(city_input) if 0 < city_input <= len(city): city_id = city_input - 1 # 市編號,因爲顯示加1,獲取的時候,須要減1 county = self.zone[self.province[province_id]][city[city_id]] # 縣列表 self.county(county) # 進入縣列表 else: print("\033[41;1m市編號 {} 不存在!\033[0m".format(city_input)) elif city_input.upper() == 'B': break elif city_input.upper() == 'Q': exit() # 因爲在多層while循環裏面,直接exit退出便可 else: print("\033[41;1m輸入市編號非法!\033[0m") def county(self, county): # 縣列表 if county == '': return 'county 參數不能爲空' while True: print('縣'.center(20, '*')) for k in county: print('{}\t{}'.format(county.index(k) + 1, k)) # 到縣這一級,不能輸入編號了,直接提示返回菜單或者退出 county_input = input("輸入b(back)返回上級菜單,或輸入q(quit)退出:").strip() if county_input == 'b': # 終止此層while循環,跳轉到上一層While break elif county_input == 'q': # 結束程序 exit() else: print("\033[41;1m已經到底線了,請返回或者退出!\033[0m") if __name__ == '__main__': AreaMenu()
執行輸出: