小猿圈python学习-对象间的交互、组合

对象间的交互

在游戏中有很多玩家,他们互砍,如何实现的?

还记得我们开头的引子么,人狗大战,用面向对象如何实现?

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 # 狗咬人,那么人的生命值就会根据狗的攻击力而下降

        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也是一个对象。

        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降

        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)

类与类之间的关系

大千世界, 万物之间皆有规则和规律. 我们的类和对象是对大千世界中的所有事物进行归类. 那事物之间存在着相对应的关系. 类与类之间也同样如此. 在面向对象的世界中. 类与类中存在以下关系:

依赖关系,狗和主人的关系

关联关系,你和你的女盆友的关系就是关联关系

组合关系,比聚合还要紧密.比如人的大脑, 心脏, 各个器官. 这些器官组合成一个人. 这时. 人如果挂了. 其他的东西也跟着挂了

聚合关系,电脑的各部件组成完整的电脑,电脑里有CPU, 硬盘, 内存等。 每个组件有自己的生命周期, 电脑挂了. CPU还是好的. 还是完整的个体

继承关系, 类的三大特性之一,子承父业

依赖关系

狗和主人的关系可以理解为是一种依赖关系,如果没有主人,它就是流浪狗了,可能会死。

class Dog:

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

        self.name = name

        self.age = age

        self.breed = breed

        self.master = master # master传进来的应该是个对象

        self.sayhi()  # 调用自己的方法在实例化的时候

    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]去溜溜。。。

关联关系

你和你女朋友的关系

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()

以上虽然实现了2个对象的关联,但细想其实是有问题的,武大郎和黑姑娘需要在自己的实例中分别绑定下彼此才能实现伴侣关系。假如有一方忘记了关联,那这个伴侣关系就只是单方面成立了,黑姑娘知道自己的另一伴是武大郎,武大郎却不识黑姑娘。

为了确保这两人的关系是一致的,怎么办呢?

可以创建个单独的类,存储2个人的关系状态,2个人在查自己的感情状态时,都到这个单独的实例里来查

class RelationShip:

    """保存2个人的感情关联关系"""

    def __init__(self):

        self.couple = []

    def make_couple(self,obj1,obj2):

        self.couple.append(obj1)

        self.couple.append(obj2)

        print("[%s] 和 [%s] 正式结为对象..." % (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("你没有对象,自己心里没有点数么....")

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个人结合在一起

p1.do_private_stuff()

p2.do_private_stuff()

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

p1.relation.get_my_partner(p1) # 再去查,就没有对象了

p2.relation.get_my_partner(p2) # 再去查,就没有对象了

组合关系

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

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也是一个对象。

        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降

        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)  # 通过组合的方式调用weapon实例下的具体武器

p.weapon.stick(d)

用组合的方式建立了类与组合的类之间的关系,它是一种‘有’或者”包含”的关系,比如老师有生日,老师教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)

输出结果:

Chinese Chinese

由于中国人的国籍都是Chinese, 此时你没必要存14亿份这个数据,存一份就好。

可如果有人改国籍怎么办?

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) # 再调用已删除的类属性就会报错了

练习题

开发一个反恐游戏,有警察、恐怖分子,还有各种武器,他们可以互砍互杀。

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

提示:可以只写一个Person类,一个weapon类。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容