一.今日主要內容:編程
1.類與類之間的關係
在咱們的世界中事物和事物之間總會有一些聯繫.
在面向對象中,類和類之間也能夠產生相關的關係
(1)依賴關係
執行某個動做(方法)的時候,須要xxx來幫助你完成這個操做,此時的關係是最輕的.
隨時能夠更換另一個東西來完成此操做
大象進冰箱&植物大戰殭屍
(2)關聯關係(在對象裏面埋對象)
老師=>學校
A.一對一關係 self.girlFriend=girl
典型案例:你和你的女友
B.一對多關係(生活中,更多的是這種關係) self.teach_list=[t1,t2,t3]
一個學校,一堆老師
C.多對多關係
類中的關係:依賴關係最輕的,最重的是繼承關係,關聯關係是比較微妙的.
2.self究竟是誰?
self:誰調用的就是誰.類型是根據調用方的對象來進行變換的(不必定是這個類)
super:與繼承相關的.(表示的是父類)
3.關聯關係=>組合=>聚合=>UML圖(一看就會清晰明瞭了)(類與類之間的關係UML圖)
4.特殊成員:(咱們沒有主動調用,而是自動調用)
__init__() #建立對象的時候初始化操做
__new__() #建立對象的時候,開闢內存
__call__() #對象()
__getitem__() #對象['冬瓜']
__setitem__() #對象['冬瓜']=值
__hash__() #可哈希 hash()
__enter__() #with 對象
__exit__() #結束with的時候
class A:
def __init__(self):
xxxx
a=A()
二.今日內容大綱:app
1.依賴關係ide
2.關聯關係函數
3.繼承關係學習
4.特殊成員優化
三.今日內容詳解:spa
1.依賴關係code
(1)依賴關係例題對象
class Person: def play(self,tools): #經過參數的傳遞把另一個類的對象傳遞進來 tools.run() print('很開心,我能玩兒遊戲了') class Computer(): def run(self): print('電腦開機,能夠運行') class Phone(): def run(self): print('手機開機,能夠運行了') c=Computer() phone=Phone() p=Person() p.play(phone)
(2)blog
#典型的依賴關係,能夠像方法進行縮進優化(思考)
#這個題目仍是有必定的深度的,在攻擊力裏邊的寫法
#寫一個植物大戰殭屍
# 1.植物
# 打殭屍,將是掉血
# 2.殭屍
# 吃植物,植物掉血
#本身寫的版本,漏洞不少,思考的靈活性仍是不夠 class plant(): def __init__(self,name,blood,gjl): self.name=name self.blood=blood self.gjl=gjl def skill(self,js): js.blood-=self.gjl print(f'殭屍掉血{self.gjl},還剩下{js.blood}') class jiangshi(): def __init__(self,name,blood,gjl): self.name=name self.blood=blood self.gjl=gjl def j_skill(self,zw): zw.blood-=self.gjl print(f'植物掉血{self.gjl},還剩下{zw.blood}') zhiwu=plant('大冬瓜',100,1) js=jiangshi('小殭屍',20,2) zhiwu.skill(js) js.j_skill(zhiwu) # pjf=pj_fight() # pjf.play(zhiwu) #老師講解 class plant(): def __init__(self,name,hp,ad): self.name = name self.hp = hp self.ad = ad def attack(self,js): #注意這裏須要名字js print('植物攻擊殭屍') js.hp-=self.ad print(f'殭屍掉血{self.ad},還剩下{js.hp}') class jiangshi(): def __init__(self,name,hp,ad): self.name = name self.hp = hp self.ad = ad def attack(self,zw): print('殭屍咬植物') zw.hp-=self.ad print(f"植物掉血{self.ad},還剩{zw.hp}") wd = plant('大冬瓜', 100, 1) js = jiangshi('小殭屍', 20, 2) wd.attack(js) wd.attack(js) wd.attack(js) js.attack(wd) js.attack(wd) js.attack(wd) js.attack(wd) #人狗大戰&西門慶與武松大戰均可以寫了
2.關聯關係
(1)一對一關係
class Boy: def __init__(self,name,girlFriend=None): #在初始化的時候能夠給一個對象的屬性設置成另外一個 類的對象 self.name=name self.girlFriend=girlFriend #一個男孩有一個女友 def chi(self): if self.girlFriend: print(f'帶着他的女友{self.girlFriend.name}去吃飯') else: print('單身狗,吃什麼吃?滾去學習') def movie(self): if self.girlFriend: print(f'帶着他的女友{self.girlFriend.name}去看電影') else: print('單身狗,吃什麼吃?滾去學習') class Girl: def __init__(self,name): self.name=name #第一步 b=Boy('寶浪') g=Girl('孫藝珍') b.chi() #第二步 #alex給寶浪介紹了一個女友,孫藝珍 b=Boy('寶浪') g=Girl('孫藝珍') b.girlFriend=g b.chi() #第三步 b=Boy('寶浪') g=Girl('孫藝珍') g2=Girl('梁詠琪') #在這裏換了女友 b.girlFriend=g2 #換了個女友 b.chi()
(2)
#一對多關係(使用率最高的關係),超級重點
#這個經過列表的建立,列表的添加,for循環列表
#與 初始化,招聘老師,上課老師 進行方法對應
class School(): def __init__(self,name): self.teach_list=[] #這裏要裝多個老師 #注意這裏搞了一個列表 #建立 self.name=name self.hehe='呵呵' #初始化時候,能夠給一些屬性 def zhaopin(self,teach): #添加 self.teach_list.append(teach) def shangke(self): for t in self.teach_list: #循環執行 t.work() class Teacher: def __init__(self,name): self.name=name def work(self): print(f'{self.name}在上課') lnh=School('老男孩') t1=Teacher('武sir') t2=Teacher('太白') t3=Teacher('哪吒') t4=Teacher('女神') t5=Teacher('日天') t6=Teacher('寶浪') lnh.zhaopin(t1) #在這個地方添加的是實例化後的對象 lnh.zhaopin(t2) lnh.zhaopin(t3) lnh.zhaopin(t4) lnh.zhaopin(t5) lnh.zhaopin(t6) lnh.shangke() #一執行,就把上邊的所有執行了 #由於上課中用到的是for遍歷列表中的細信息
3.繼承關係
(1)
class Base: def chi(self): print('我會吃') #派生類=>就是子類 class Foo(Base): #這個類繼承了Base類,Foo類是對Base的一個擴展 def he(self): print('我會喝') f=Foo() f.chi() f.he()
(2)
#注意名稱的描述 class Cat: #父類=>基類(超類) def catch_mouse(self): print("貓能夠抓老鼠") class BosiCat(Cat): #子類=>派生類 pass
(3)
class Foo: pass print(hash(Foo)) #可哈希 print(hash(Foo())) #可哈希 #總結:咱們寫好的類和建立的對象默認都是可哈希的 class Foo: __hash__=None print(hash(Foo)) #可哈希 print(hash(Foo())) #unhashable type: 'Foo' #類永遠是可哈希的,可是加上__hash__=None, # 對象就不可哈希了
(4)
#利用字典進行調用 class Foo: def chi(self): print('我愛吃魚') class Bar: def chi(self): print('我愛吃肉') dic ={Foo:Foo(),Bar:Bar()} for k,v in dic.items(): v.chi()
(5)
#利用字典調用=>升級 class Foo: def chi(self,food): print('我愛吃魚和',food) class Bar: def chi(self,food): print('我愛吃肉和',food) dic ={Foo:'雞蛋',Bar:'香腸'} for k,v in dic.items(): k().chi(v)
(6)self系列
# self中 先找本身的,再找父類的 #對比函數進行回顧: # 類名 => 變量名 ->相同的道理 # def func(): # pass # # an = func # an()
class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) class Foo(Base): pass obj = Foo(123) obj.func1() ''' 結果: 123 '''
class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) class Foo(Base): def func1(self): print("Foo. func1", self.num) obj = Foo(123) obj.func1() ''' 結果: Foo. func1 123 '''
class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) self.func2() def func2(self): print("Base.func2") class Foo(Base): def func2(self): print("Foo.func2") obj = Foo(123) obj.func1() ''' 結果: 123 Foo.func2 '''
class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) self.func2() def func2(self): print(111, self.num) class Foo(Base): def func2(self): print(222, self.num) lst = [Base(1), Base(2), Foo(3)] for obj in lst: obj.func2() ''' 結果: 111 1 111 2 222 3 '''
class Base: def __init__(self, num): self.num = num def func1(self): print(self.num) self.func2() def func2(self): print(111, self.num) class Foo(Base): def func2(self): print(222, self.num) lst = [Base(1), Base(2), Foo(3)] for obj in lst: obj.func1() ''' 結果: 1 111 1 2 111 2 3 222 3 '''
4.特殊成員
(1)
class Foo: def __init__(self): print('初始化操做,在建立對象的時候自動調用這個方法') f=Foo() #自動執行__init__() f.__init__() #第一次這麼寫,之後不要這麼寫 #上邊兩行是等價的
(2)
# 回顧:三大器1 # lst=[] # lst.__iter__() #回顧內置函數 # lst=[1,2,3,4] # it=iter(lst) # print(it.__next__()) # print(next(it))
(3)
#callable 可調用的 判斷xxx是不是可調用的 # 曾經的例子: # def func(): # pass # print(callable(func)) # func=3 # print(callable(func)) #此時變成不可調用的 # class Foo: # def __init__(self): # print('初始化操做,在建立對象的時候自動調用這個方法') # f=Foo() #結果:初始化操做,在建立對象的時候自動調用這個方法 # print(callable(f)) #False 說明對象不可調用 # #__call__()的做用: # class Foo: # def __init__(self): # print('初始化操做,在建立對象的時候自動調用這個方法') # # #爲了對象可以被調用而生的 f() # def __call__(self, *args, **kwargs): # print('我是對象()') # f=Foo() #初始化操做,在建立對象的時候自動調用這個方法 # f() #我是對象(), 調用的是__call__內的東西 # print(callable(f)) #True
(4)
#__getitem__ 字典,元組,列表都是用的這個 (給值) # class Foo: # #對象[] # def __getitem__(self, item): # print('item=',item) # print('你執行了__getitem__') # return '哈哈' # f=Foo() #初始化操做,在建立對象的時候自動調用這個方法 # print(f['李嘉誠']) ''' 結果: item= 李嘉誠 你執行了__getitem__ 哈哈 '''
(5)
#__setItem__()方法 # class Foo: # def __setitem__(self, key, value): # print("key, ", key) # print("value, ", value) # f=Foo() # f['jay'] = "林俊杰" ''' 結果: key, jay value, 林俊杰 '''
(6)
# __delitem__()方法 # class Foo: # def __delitem__(self, key): # print('key=',key) # f=Foo() # del f['哈哈'] ''' 結果: key= 哈哈 '''
(7)
# __enter__() 方法 #__exit__()方法 # class Foo: # # with 對象: # def __enter__(self): # print("我是enter") # # with 對象: 代碼執行完畢. 最後執行這裏 # def __exit__(self, exc_type, exc_val, exc_tb): # print("我叫exit") # f=Foo() # with f: # print("我是哈哈哈哈") ''' 結果: 我是enter 我是哈哈哈哈 我叫exit '''
(8)
# class Foo: # def __init__(self): # 初始化操做 # print("我是init, 我是老二") # print("初始化操做. 在建立對象的時候自動調用這個方法") # # def __new__(cls, *args, **kwargs): # 建立, 它是真正的構造方法, 能夠開闢內存 # print("我是new. 我是老大") #在開闢內存以前能夠放東西 # return object.__new__(cls)
(9)
# lst = ["孫藝珍", "李金珠", "井柏然"] # # lst[2] # =>自動的調用__getitem__()
(10)
面向對象編程的執行流程=>
1.加載類=>給類建立一個名稱空間=>主要存放類變量
2.建立對象=>先找類=>根據類來開闢內存=>
執行類中的__new__() -> 執行__init__() -> 返回對象
(11)
#__str__() and __repr__() class Student: def __init__(self,name,no,gender,cls,age): self.name=name self.no=no self.gender=gender self.cls=cls self.age=age # 遇到出不來,兩個都嘗試一下 # 若是隻是內存地址,再寫另外一個試試 #這個對象字符串的表示 # def __str__(self): #返回該對象的字符串表示形式 # return f'{self.name},{self.no},{self.gender}' # def __repr__(self): #該對象的官方的字符串表示形式 # return f'{self.name},{self.no},{self.gender}' s = Student("冬瓜", "3", "男", "S18", "31") print(s)
做業講解:記得補充: