小猿圈python學(xué)習(xí)-對象間的交互、組合

對象間的交互

在游戲中有很多玩家,他們互砍,如何實現(xiàn)的?

還記得我們開頭的引子么,人狗大戰(zhàn),用面向?qū)ο笕绾螌崿F(xiàn)?

class Dog:? # 定義一個狗類

? ? role = 'dog'? # 狗的角色屬性都是狗

? ? def __init__(self, name, breed, attack_val):

? ? ? ? self.name = name

? ? ? ? self.breed = breed? # 每一只狗都有自己的品種;

? ? ? ? self.attack_val = attack_val? # 每一只狗都有自己的攻擊力;

? ? ? ? self.life_val = 100? # 每一只狗都有自己的生命值;

? ? def bite(self, person):

? ? ? ? # 狗可以咬人,這里傳遞進來的person也是一個對象。

? ? ? ? person.life_val -= self.attack_val # 狗咬人,那么人的生命值就會根據(jù)狗的攻擊力而下降

? ? ? ? print("狗[%s]咬了人[%s],人掉血[%s],還剩血量[%s]..." % (self.name,person.name,self.attack_val,person.life_val))

class Person:? # 定義一個人類

? ? role = 'person'? # 人的角色屬性都是人

? ? def __init__(self, name, sex, attack_val):

? ? ? ? self.name = name

? ? ? ? self.attack_val = attack_val

? ? ? ? self.life_val = 100

? ? ? ? self.sex = sex

? ? def attack(self,dog):

? ? ? ? # 人可以攻擊狗,這里傳遞進來的dog也是一個對象。

? ? ? ? # 人攻擊狗,那么狗的生命值就會根據(jù)人的攻擊力而下降

? ? ? ? dog.life_val -= self.attack_val

? ? ? ? print("人[%s]打了狗[%s],狗掉血[%s],還剩血量[%s]..." % (self.name,dog.name,self.attack_val,dog.life_val))

d = Dog("mjj","二哈",20)

p = Person("Alex","Male",60)

d.bite(p) # 對象交互,把p實例傳遞給d的方法

p.attack(d)

類與類之間的關(guān)系

大千世界, 萬物之間皆有規(guī)則和規(guī)律. 我們的類和對象是對大千世界中的所有事物進行歸類. 那事物之間存在著相對應(yīng)的關(guān)系. 類與類之間也同樣如此. 在面向?qū)ο蟮氖澜缰? 類與類中存在以下關(guān)系:

依賴關(guān)系,狗和主人的關(guān)系

關(guān)聯(lián)關(guān)系,你和你的女盆友的關(guān)系就是關(guān)聯(lián)關(guān)系

組合關(guān)系,比聚合還要緊密.比如人的大腦, 心臟, 各個器官. 這些器官組合成一個人. 這時. 人如果掛了. 其他的東西也跟著掛了

聚合關(guān)系,電腦的各部件組成完整的電腦,電腦里有CPU, 硬盤, 內(nèi)存等。 每個組件有自己的生命周期, 電腦掛了. CPU還是好的. 還是完整的個體

繼承關(guān)系, 類的三大特性之一,子承父業(yè)

依賴關(guān)系

狗和主人的關(guān)系可以理解為是一種依賴關(guān)系,如果沒有主人,它就是流浪狗了,可能會死。

class Dog:

? ? def __init__(self,name,age,breed,master):

? ? ? ? self.name = name

? ? ? ? self.age = age

? ? ? ? self.breed = breed

? ? ? ? self.master = master # master傳進來的應(yīng)該是個對象

? ? ? ? self.sayhi()? # 調(diào)用自己的方法在實例化的時候

? ? def sayhi(self):

? ? ? ? print("Hi, I'm %s, a %s dog, my master is %s" %(self.name,self.breed,self.master.name))

class Person:

? ? def __init__(self,name,age,sex):

? ? ? ? self.name = name

? ? ? ? self.age = age

? ? ? ? self.sex = sex

? ? def walk_dog(self,dog_obj):

? ? ? ? """遛狗"""

? ? ? ? print("主人[%s]帶狗[%s]去溜溜。。。" % (self.name,dog_obj.name ))

p = Person("Alex",26,"Male")

d = Dog("Mjj",5,"二哈",p)

p.walk_dog(d)

輸出

Hi, I'm Mjj, a 二哈 dog, my master is Alex

主人[Alex]帶狗[Mjj]去溜溜。。。

關(guān)聯(lián)關(guān)系

你和你女朋友的關(guān)系

class Person:

? ? def __init__(self,name,age,sex):

? ? ? ? self.name = name

? ? ? ? self.age = age

? ? ? ? self.sex = sex

? ? ? ? self.partner = None # 另一半,是個對象

? ? def do_private_stuff(self):

? ? ? ? """和男/女盆友干點羞羞的事"""

? ? ? ? print("%s is doing %s in the 7th hotel." %(self.name,self.partner.name))

p1 = Person("武大郎",25,"男")

p2 = Person("黑姑娘",23,"女")

p1.partner = p2 # 兩個對象要互相綁定彼此

p2.partner = p1

p1.do_private_stuff()

p2.do_private_stuff()

以上雖然實現(xiàn)了2個對象的關(guān)聯(lián),但細想其實是有問題的,武大郎和黑姑娘需要在自己的實例中分別綁定下彼此才能實現(xiàn)伴侶關(guān)系。假如有一方忘記了關(guān)聯(lián),那這個伴侶關(guān)系就只是單方面成立了,黑姑娘知道自己的另一伴是武大郎,武大郎卻不識黑姑娘。

為了確保這兩人的關(guān)系是一致的,怎么辦呢?

可以創(chuàng)建個單獨的類,存儲2個人的關(guān)系狀態(tài),2個人在查自己的感情狀態(tài)時,都到這個單獨的實例里來查

class RelationShip:

? ? """保存2個人的感情關(guān)聯(lián)關(guān)系"""

? ? def __init__(self):

? ? ? ? self.couple = []

? ? def make_couple(self,obj1,obj2):

? ? ? ? self.couple.append(obj1)

? ? ? ? self.couple.append(obj2)

? ? ? ? print("[%s] 和 [%s] 正式結(jié)為對象..." % (obj1.name,obj2.name))

? ? def break_up(self):

? ? ? ? if self.couple:

? ? ? ? ? ? print("[%s] 和 [%s] 要分手了...真好" % (self.couple[0].name,self.couple[1].name))

? ? ? ? ? ? self.couple.clear()

? ? ? ? else:

? ? ? ? ? ? print("你根本就沒對象,你分手個蛋呀...")

? ? def get_my_partner(self,obj):

? ? ? ? """返回我的另一半"""

? ? ? ? for i in self.couple:

? ? ? ? ? ? if obj != i: # copule列表里有2個值,一個是我自己,一個是我對象,只要跟傳進來的obj不相等,代表找到了我對象

? ? ? ? ? ? ? ? return i.name

? ? ? ? else:

? ? ? ? ? ? print("你沒有對象,自己心里沒有點數(shù)么....")

class Person:

? ? def __init__(self,name,age,sex,relation_obj):

? ? ? ? self.name = name

? ? ? ? self.age = age

? ? ? ? self.sex = sex

? ? ? ? self.relation = relation_obj # 把RelationShip對象傳進來

? ? ? ? #self.partner = None # 另一半,是個對象

? ? def do_private_stuff(self):

? ? ? ? """和男/女盆友干點羞羞的事"""

? ? ? ? print("%s is doing %s in the 7th hotel." %(self.name,self.relation.get_my_partner(self)))

relation_obj = RelationShip()

p1 = Person("武大郎",25,"男",relation_obj)

p2 = Person("黑姑娘",23,"女",relation_obj)

relation_obj.make_couple(p1,p2) # 把2個人結(jié)合在一起

p1.do_private_stuff()

p2.do_private_stuff()

p1.relation.break_up() # 要分手了

p1.relation.get_my_partner(p1) # 再去查,就沒有對象了

p2.relation.get_my_partner(p2) # 再去查,就沒有對象了

組合關(guān)系

組合指的是,在一個類中以另外一個類的對象作為數(shù)據(jù)屬性,稱為類的組合

class Dog:? # 定義一個狗類

? ? role = 'dog'? # 狗的角色屬性都是狗

? ? ......

class Weapon:

? ? def stick(self,obj):

? ? ? ? """打狗棒"""

? ? ? ? self.name = "打狗棒"

? ? ? ? self.attack_val = 40

? ? ? ? obj.life_val -= self.attack_val

? ? ? ? self.print_log(obj)

? ? def knife(self,obj):

? ? ? ? """屠龍刀"""

? ? ? ? self.name = "屠龍刀"

? ? ? ? self.attack_val = 80

? ? ? ? obj.life_val -= self.attack_val

? ? ? ? self.print_log(obj)

? ? def gun(self,obj):

? ? ? ? """AK47"""

? ? ? ? self.name = "AK47"

? ? ? ? self.attack_val = 100

? ? ? ? obj.life_val -= self.attack_val

? ? ? ? self.print_log(obj)

? ? def print_log(self,obj):

? ? ? ? print("[%s]被[%s]攻擊了,掉血[%s],還剩血量[%s]..." %(obj.name,self.name,self.attack_val,obj.life_val))

class Person:? # 定義一個人類

? ? role = 'person'? # 人的角色屬性都是人

? ? def __init__(self, name, sex, attack_val):

? ? ? ? self.name = name

? ? ? ? self.attack_val = attack_val

? ? ? ? self.life_val = 100

? ? ? ? self.sex = sex

? ? ? ? self.weapon = Weapon() # 在此處實例化一個Weapon對象

? ? def attack(self,dog):

? ? ? ? # 人可以攻擊狗,這里傳遞進來的dog也是一個對象。

? ? ? ? # 人攻擊狗,那么狗的生命值就會根據(jù)人的攻擊力而下降

? ? ? ? dog.life_val -= self.attack_val

? ? ? ? print("人[%s]打了狗[%s],狗掉血[%s],還剩血量[%s]..." % (self.name,dog.name,self.attack_val,dog.life_val))

d = Dog("mjj","二哈",20)

p = Person("Alex","Male",60)

d.bite(p) # 對象交互,把p實例傳遞給d的方法

p.attack(d)

p.weapon.knife(d)? # 通過組合的方式調(diào)用weapon實例下的具體武器

p.weapon.stick(d)

用組合的方式建立了類與組合的類之間的關(guān)系,它是一種‘有’或者”包含”的關(guān)系,比如老師有生日,老師教python課程。 你有女朋友,你朋友有自己的一些特征

class BirthDate:

? ? def __init__(self, year, month, day):

? ? ? ? self.year = year

? ? ? ? self.month = month

? ? ? ? self.day = day

class Course:

? ? def __init__(self, name, price, period):

? ? ? ? self.name = name

? ? ? ? self.price = price

? ? ? ? self.period = period

class Teacher:

? ? def __init__(self, name, gender, birth, course):

? ? ? ? self.name = name

? ? ? ? self.gender = gender

? ? ? ? self.birth = birth

? ? ? ? self.course = course

? ? def teaching(self):

? ? ? ? print('teaching.....',self.course.name)

p1 = Teacher('Alex', 'Male',

? ? ? ? ? ? BirthDate('1995', '1', '27'),

? ? ? ? ? ? Course('Python', '28000', '5 months')

? ? ? ? ? ? )

print(p1.birth.year, p1.birth.month, p1.birth.day)

print(p1.course.name, p1.course.price, p1.course.period)

當類之間有顯著不同,并且較小的類是較大的類所需要的組件時,用組合比較好

類變量的用途

我們知道類變量是存在類里,實例變量存在每個實例里,那什么時候用類變量呢?

例子:我要把中國14億人的都分別生成一個實例。

class Person:

? ? nationality = "Chinese"

? ? def __init__(self,name,sex,birthday,hometown):

? ? ? ? self.name = name

? ? ? ? self.sex = sex

? ? ? ? self.birthday = birthday

? ? ? ? self.hometown = hometown

p1 = Person("Alex","Male","1995-05-32","山東德州")

p2 = Person("Mjj","Ladyboy","1992-06-16","河南信陽")

print(p1.nationality,p2.nationality)

輸出結(jié)果:

Chinese Chinese

由于中國人的國籍都是Chinese, 此時你沒必要存14億份這個數(shù)據(jù),存一份就好。

可如果有人改國籍怎么辦?

p2.nationality = "Japan"? # 這個動作相當于把p2.nationality變成了實例變量

print(p1.nationality,p2.nationality)

輸出:

Chinese Japan? # 并不會影響p1的國籍

屬性的增刪改查

class Person:

? ? nationality = "Chinese"

? ? addr = "北京"

? ? def __init__(self,name,age,sex):

? ? ? ? self.name = name

? ? ? ? self.age = age

? ? ? ? self.sex = sex

# 實例屬性操作

p = Person("Alex",26,"Male")

p.name = "Alex Li 金角大王" # 修改屬性

p.job = "CEO" # 添加實例屬性

del p.sex # 刪除實例屬性

print(p.job)? #打印添加的實例屬性

# 類屬性操作

Person.nationality = "US"

Person.race = "Yellow" # 添加類屬性

del Person.addr

print(p.addr) # 再調(diào)用已刪除的類屬性就會報錯了

練習(xí)題

開發(fā)一個反恐游戲,有警察、恐怖分子,還有各種武器,他們可以互砍互殺。

注意,警察不能用炸藥包,恐怖分子可以。炸藥包一用,全部玩家都得死。

提示:可以只寫一個Person類,一個weapon類。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容