Python面向对象 | 组合

软件重用的重要方式,除了继承之外还有另外一种方式,即:组合

一、对象之间的交互

方法可以传参,参数可以是对象。

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,dog):
        dog.hp -= self.ad
        print('%s攻击了%s,%s掉了%s点血' % (self.name,dog.name,dog.name,self.ad))

class Dog:
    role = 'person'

    def __init__(self, name, kind, hp, ad):
        self.name = name
        self.kind = kind
        self.hp = hp
        self.ad = ad

    def bite(self,people):             #people是变量名,它是一个对象
        people.hp -= self.ad 
        print('%s咬了%s一口,%s掉了%s点血' % (self.name, people.name, people.name, self.ad))

tony = Person('Tony', '不详', 1, 5)
john = Person('John', '', 20, 50)
teddy = Dog('teddy', 'male', 50, 10)

teddy.bite(tony)               
print(tony.hp)                  

tony.attack(teddy)
print(teddy.hp)

'''
执行输出:
teddy咬了Tony一口,Tony掉了10点血
-9
Tony攻击了teddy,teddy掉了5点血
45
'''

、面向对象的组合

组合:给一个类的对象封装一个属性,这个属性就是另一个类的对象

组合的意义:让一个类的对象和另一个类的对象产生关系,让一个类和另一个类产生关系

如何组合:

  1、在类1中定义一个方法,类1对象1在执行这个方法的时候能增加一个属性,属性值就是类2的对象2;

  2、类1.属性名.类2中的方法,就以类1为主体执行了类2的方法;

当一个类的对象作为另一个类的属性,说明这2个类组合在一起了。那么类就可以使用另外一个类的属性和方法了。一般说组合 ,是指2个类的组合。

class Gamerole:
    def __init__(self,name,ad,hp):
        self.name = name
        self.hp = hp
        self.ad = ad

    def attack(self,role):
        role.hp = role.hp - self.ad
        print('%s攻击%s,%s掉了%s血,还剩%s血' % (self.name,role.name,role.name,self.ad,role.hp))

  #定义一个方法,让Gamerole的对象可以产生一个新的属性,属性名是weapon,属性值是Weapon的对象
    def equip_weapon(self,w):  
        self.weapon = w

class Weapon:
    def __init__(self,name,ad):
        self.name = name
        self.ad = ad

    def fight(self,role1,role2):
        role2.hp = role2.hp - self.ad
        print('%s用%s攻击%s,%s掉了%s血,还剩%s' %(role1.name,self.name,role2.name,role2.name,self.ad,role2.hp))

p1 = Gamerole('盖伦',20,500)
p2 = Gamerole('剑豪',100,200)
p1.attack(p2)

w1 = Weapon('大宝剑',30)
w2 = Weapon('武士刀',80)
w1.fight(p1,p2)              #刀是主体,不合规范 盖伦用大宝剑攻击剑豪,剑豪掉了30血,还剩170血

p1.equip_weapon(w1)          #执行方法,给对象p1增加一个属性weapon,属性值是Weapon的对象w1
# print(p1.weapon)           #<__main__.Weapon object at 0x000001FF47997AC8>
# print(w1)                  #<__main__.Weapon object at 0x000001FF47997AC8> 地址相同
p1.weapon.fight(p1,p2)       #盖伦用大宝剑攻击剑豪,剑豪掉了30血,还剩170血

、组合实例

1.人狗大战武器给谁装备呢?武器需要花钱买吧,那么就需要玩家充钱,现在加一个充钱功能

class Person:
    def __init__(self, name, sex, hp, ad):
        self.name = name  # 对象属性 属性
        self.sex = sex
        self.hp = hp  # 血量
        self.ad = ad  # 攻击力
        self.money = 0  # 金额
        self.arms = None  # 默认武器为None

    def attack(self, d):
        d.hp -= self.ad
        print('%s攻击了%s,%s掉了%s点血' % (self.name, d.name, d.name, self.ad))

    def pay(self):                    # 充值
        money = int(input('请输入您要充值的金额:'))
        self.money += money
        print('您的余额是:%s' % self.money)

    def wear(self, weapon):              # 装备武器
        if self.money >= weapon.price:
            self.arms = weapon            # 组合 给人装备了武器
            self.money -= weapon.price
            print('购买成功,您已经顺利装备了%s' % weapon.name)
        else:
            print('余额不足,请充值!')

    def attack_with_weapon(self, dog):  # 拿武器攻击狗
        if 'arms' in self.__dict__ and self.arms != None:  # 如果武器属性在实例属性字典里,并且属性不为空
            self.arms.skill(dog)  # 使用武器攻击狗
        else:
            print('请先装备武器')


class Dog:
    def __init__(self, name, kind, hp, ad):
        self.name = name  # 对象属性 属性
        self.kind = kind
        self.hp = hp
        self.ad = ad

    def bite(self, p):
        p.hp -= self.ad  # 人掉血
        print('%s咬了%s一口,%s掉了%s点血' % (self.name, p.name, p.name, self.ad))


class Weapon:  # 武器
    def __init__(self, name, price, level, ad):
        self.name = name  # 武器名
        self.price = price  # 价格
        self.level = level  # 等级
        self.ad = ad * self.level  # 升级之后,攻击就翻倍了
        self.wear = 20  # 默认的耐久度,实例化时,可以不用传

    def skill(self, dog):  # 技能,攻击狗
        dog.hp -= self.ad  # 狗掉血
        print('%s受到了%s点的伤害,%s掉了%s点血' % (dog.name, self.name, dog.name, self.ad))


# 实例化武器,玩家购买武器,攻击狗
tony = Person('Tony', '不详', 1, 5)
tony.pay()                              # 充值
tony.wear(axe)                          # 装备武器斧头
tony.arms.skill(teddy)                  # 使用斧头攻击狗 ,相当于tony.skill(reddy)

注意:不能加类静态变量meny = 0。否则玩家充钱了,别的玩家就可以使用了,int之后,不需要strip()一下,int会自动去除空格

这样写是一次性的,写一个while循环,显示菜单执行。实例化部分,改成如下:

class Person:
    def __init__(self, name, sex, hp, ad):
        self.name = name  # 对象属性 属性
        self.sex = sex
        self.hp = hp  # 血量
        self.ad = ad  # 攻击力
        self.money = 0  # 金额
        self.arms = None  # 默认武器为None

    def attack(self, d):
        d.hp -= self.ad
        print('%s攻击了%s,%s掉了%s点血' % (self.name, d.name, d.name, self.ad))

    def pay(self):  # 充值
        money = int(input('请输入您要充值的金额:'))
        self.money += money
        print('您的余额是:%s' % self.money)

    def wear(self, weapon):  # 装备武器
        if self.money >= weapon.price:
            self.arms = weapon  # 组合 给人装备了武器
            self.money -= weapon.price
            print('购买成功,您已经顺利装备了%s' % weapon.name)
        else:
            print('余额不足,请充值!')

    def attack_with_weapon(self, dog):  # 拿武器攻击狗
        if 'arms' in self.__dict__ and self.arms != None:  # 如果武器属性在实例属性字典里,并且属性不为空
            self.arms.skill(dog)  # 使用武器攻击狗
        else:
            print('请先装备武器')


class Dog:
    def __init__(self, name, kind, hp, ad):
        self.name = name  # 对象属性 属性
        self.kind = kind
        self.hp = hp
        self.ad = ad

    def bite(self, p):
        p.hp -= self.ad  # 人掉血
        print('%s咬了%s一口,%s掉了%s点血' % (self.name, p.name, p.name, self.ad))


class Weapon:  # 武器
    def __init__(self, name, price, level, ad):
        self.name = name  # 武器名
        self.price = price  # 价格
        self.level = level  # 等级
        self.ad = ad * self.level  # 升级之后,攻击就翻倍了
        self.wear = 20  # 默认的耐久度,实例化时,可以不用传

    def skill(self, dog):  # 技能,攻击狗
        dog.hp -= self.ad  # 狗掉血
        print('%s受到了%s点的伤害,%s掉了%s点血' % (dog.name, self.name, dog.name, self.ad))


# 实例化武器,玩家购买武器,攻击狗
tony = Person('Tony', '不详', 1, 5)
teddy = Dog('Teddy', 'teddy', 50, 10)
axe = Weapon('Axe', 1000, 100, 1)
lst = ['攻击', '充值', '装备武器', '使用武器攻击','退出']
while True: for index, value in enumerate(lst, 1): print(index, value) num = int(input('请选择操作序号 >>>')) if num == 1: tony.attack(teddy) elif num == 2: tony.pay() elif num == 3: print('装备前余额 %s' % tony.money) tony.wear(axe) print('装备后余额 %s' % tony.money) elif num == 4: tony.attack_with_weapon(teddy) elif num == 5: break else: print('无效的序号')

执行输出:

skill方法,只有武器才有,人是不能直接调用的。但是,人一旦装备上了武器,就可以执行skill方法。关键点,就在于以下一段代码self.arms = weapon  组合 给人装备了武器 .  直接给人加了一个属性arms,注意,等式右边的weapon是一个武器对象所以就可以使用武器攻击狗self.arms.skill(dog) .  self也就是实例对象,比如tony。

为什么会用组合?

  独立的对象不能发挥他的作用,必须依赖一个对象,比如上面的例子,斧头不能够攻击狗,它依赖人来执行。

人还可以装备2件武器

tony = Person('Tony', '不详', 1, 5)
teddy = Dog('Teddy', 'teddy', 50, 10)
axe = Weapon('Axe', 1000, 100, 1)
knife = Weapon('Knife', 1000, 100, 1)
tony.pay()                                  # 充值
tony.wear(axe)                              # 装备武器斧头
tony.wear(knife)                            # 装备武器刀
tony.arms.skill(teddy)                      # 执行攻击   后一个是knife,所以alex.arms是knife

执行输出:

2.圆环

计算圆环的面积和周长

  圆环的周长 :大圆周长 + 小圆周长

  圆环的面积 :大圆面积 - 小圆面积

from math import pi
class Circle:  # 圆形
    def __init__(self, r):
        self.r = r

    def cal_area(self):  # 面积
        return pi * self.r ** 2

    def cal_perimeter(self):  # 周长
        return pi * self.r * 2


class Ring2:  # 圆环
    def __init__(self, out_r, in_r):
        self.out_circle = Circle(out_r)             # 实例化圆作为圆环的大圆
        self.in_circle = Circle(in_r)               # 实例化圆,作为圆环的小圆

    def area(self):                                 # 圆环面积.用绝对值,保证结果不为负数
        return abs(self.out_circle.cal_area() - self.in_circle.cal_area())  # 大圆面积 - 小圆面积

    def cal_perimeter(self):
        return self.out_circle.cal_perimeter() + self.in_circle.cal_perimeter()  # 大圆周长 + 小圆周长

r1 = Ring2(10, 5)  # 实例化圆环,传入大圆和小圆的半径
print(r1.area())
print(r1.cal_perimeter())

'''
执行输出:
235.61944901923448
94.24777960769379
'''

圆环包含了圆,而圆的面积和周长公式,和圆环有点类似。所以,把圆这个对象,作为圆环类对象的属性,这就是组合。

3.老师和班级

  老师 属性:姓名 年龄 性别 班级 : s11

  班级 属性:班级名 班级人数 科目 性质

class Class:
    def __init__(self, name, num, course, type):
        self.name = name
        self.num = num
        self.course = course
        self.type = type

class Teacher:
    def __init__(self, name, sex, age, cls):
        self.name = name
        self.sex = sex
        self.age = age
        self.cls = cls                          # 班级


py = Class('Python', 89, 'python', 'IT')        # 实例化一个班级
teacher = Teacher('Tony', '', 40,py)          # 实例化一个老师

print(py.course)                                # 查看课程
print(teacher.cls.course)                       # 查看课程
print(teacher.cls.__dict__)                     # 查看py11的所有属性

'''
执行输出:
python
python
{'name': 'Python', 'num': 89, 'course': 'python', 'type': 'IT'}
'''

通过实例化,可以直接组合2个类。在这个例子中,Teacher通过cls属性,得到了py对象的所有属性以及方法。这是组合的第二种使用方式

 

猜你喜欢

转载自www.cnblogs.com/Summer-skr--blog/p/11801390.html