类与对象的命名空间、组合、继承

---恢复内容开始---

# 类与对象的名称空间

class Game_role:

    name = "LOL"
    year = 2012

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

    def attack(self, obj2):
        Game_role.area = "德玛西亚"
        print("%s攻击了%s, %s掉了%s血,还剩%s血" % (self.name,
                                          obj2.name,
                                          obj2.name,
                                          self.ad,
                                          obj2.hp-self.ad))

p1 = Game_role("盖伦", 10, 100)
p2 = Game_role("剑豪", 20, 80)
print(p1.attack(p2))

p1.armor = 90
print(p1.__dict__)
# 对象的属性不仅可以在 __init__ 添加,还能再其他地方添加

p2.attack(p1)
print(Game_role.__dict__)
# 类的属性,不仅在类内部添加,还可以在类的外部添加
Game_role.year = 6
print(Game_role.__dict__)

p1 = Game_role("盖伦", 10, 100)
print(p1.name)  # 这里不是打印 LOL,而是 盖伦

# 实例化对象先从对象本身的空间找name,没有的话就找类里面的name
# 因为对象空间中存在一个类对象指针,所以对象可以找到类中的变量以及方法
# 类名只能找到类中的变量及方法,或者父类中找,不能找对象中的属性
# 对象与对象之间原则上是不能相互访问的
print(p1.year)  # 6

p3 = Game_role("提莫", 30, 60)

 

# 一. 类名称空间与对象的名称空间
# 类一创建在内存中就会创建该类的名称空间,用来存储类中定义的所有名字,这些名字都是类的属性
# 类的属性有两种:
#   1. 静态属性——直接在类中定义的变量
#   2. 动态属性就是定义在类中的方法

# 类的数据属性对于所有对象来说是共享的
class Person:
    language = "人类语言"
    age = 18

    def __init__(self):
        pass

    def attack(self, a):
        pass

p1 = Person()
p2 = Person()
print(id(p1.language), id(p2.language))
# 2645986525440 2645986525440
print(id(p1.age), id(p2.age))
# 1700162848 1700162848

# 注意这里并不是p1改变了类的静态属性,对象只能查看
# 因此相当于在该对象的内存中开辟了一个空间,存放对象的age属性与值20的对应关系
p1.age = 20
print(p1.age)  # 20
print(p2.age)  # 18
print(id(p1.age), id(p2.age))
# 1700162912 1700162848

# 而类的动态属性是绑定到所有对象的
# 因此这里对象p1调用 attack 方法时可以把自己传进去
# p1.attack(p1) 不会报错

# 总结:
# 创建一个对象\实例就会创建一个该对象\实例的名称空间
# 存放对象\实例的名字,称为对象\实例的属性
# obj.name 会从 obj 的名称空间找name, 找不到就去类中找,再找不到就找父类...最后找不到抛出异常

 

# 组合
# 计算有多少对象调用一个类

class A:
    count = 0
    def __init__(self):
        A.count += 1

obj = A()
obj1 = A()
print(A.count)


# 组合:将一个对象封装到另一个对象的属性中

class Game_role:

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

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



class Weapen:

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

    def weapen_attack(self, p1, p2):
        p2.hp -= self.ad + p1.ad  # 这里会受到人和枕头的伤害
        print("%s利用%s攻击了%s,%s还剩%s血" % (p1.name, self.name, p2.name, p2.name, p2.hp))

p1 = Game_role("盖伦", 10, 100)
p2 = Game_role("剑豪", 20, 80)
# p1.attack(p2)

pillow = Weapen("枕头", 2)
pillow.weapen_attack(p1, p2)
# 这里有个奇怪的地方,即武器是发起者,应该是人作为发起者才合理

# 为了让程序看起来合理,即要人来作为发起者,可以这样: class Game_role: def __init__(self, name, ad, hp): self.name = name self.ad = ad self.hp = hp def attack(self, obj2): print("%s攻击了%s, %s掉了%s血,还剩%s血" % (self.name, obj2.name, obj2.name, self.ad, obj2.hp-self.ad)) def equip_weapen(self, w): self.w = w # 封装属性,给一个对象封装一个属性,该属性是另一个类的对象 class Weapen: def __init__(self, name, ad): self.name = name self.ad = ad def weapen_attack(self, p1, p2): p2.hp -= self.ad + p1.ad # 这里会受到人和枕头的伤害 print("%s利用%s攻击了%s,%s还剩%s血" % (p1.name, self.name, p2.name, p2.name, p2.hp)) p1 = Game_role("盖伦", 10, 100) p2 = Game_role("剑豪", 20, 80) # p1.attack(p2) pillow = Weapen("枕头", 2) pillow.weapen_attack(p1, p2) print(p1.__dict__) # {'name': '盖伦', 'ad': 10, 'hp': 100} p1.equip_weapon(666) print(p1.w) # 666 print(p1.__dict__) # {'name': '盖伦', 'ad': 10, 'hp': 100, 'weapen': 666} # 给人物装备武器 p1.equip_weapen(pillow) # 对象p1调用类 Game_role 的方法 equip_weapen
# 而 equip_weapen 返回的是一个形参 w
# p1调用它的时候,相当于给p1增加了一个属性w,而这里这个属性接收的实参是pillow
print(p1.__dict__)
# {'name': 'a', 'ad': 20, 'hp': 100, 'w': <__main__.Weapen_1 object at 0x00000166EB9D8D68>}
# 也就是说,p1.w = pillow p1.w.weapen_attack(p1, p2) # 盖伦利用枕头攻击了剑豪,剑豪还剩68血 # 这样看起来就是p1发起的攻击,这样就具备了合理性 # 组合的好处 # 1. 使代码更合理 # 2. 类与类之间的耦合性增强(耦合性也不是越强越好)

 

# 二. 面向对象的三大特性:
# 继承
# 多态
# 封装

# 继承
# 继承是一种创建新类的方式,新建的类可以继承一个或多个父类
# 父类又称为基类或超类,新建的类称为子类或派生类
class Animal:
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

class Person:
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

class Cat:
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

class Dog:
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age
# 可以看出上面每个类中有很多相同的属性

 

class Animal:

    type_name = "动物类"

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

    def eat(self):
        print("吃东西")

# Animal: 父类
# Person, Cat, Dog: 子类

class Person(Animal):
    # type_name = "人类"
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

class Cat(Animal):
    pass

class Dog(Animal):
    pass

# 子类可以调用父类的属性和方法
Person.eat(111)
print(Person.type_name)  # 动物类

# 如果子类中也有 type_name 这个变量,则只调用它自己的属性
print(Person.type_name)  # 人类

# 对象:
# 实例化对象
p1 = Person("小春", "", 28)
# 这里Person类并没有 __init__ p1会调用父类的 __init__
print(p1.__dict__) # {'name': '小春', 'sex': '', 'age': 28}
p1.type_name = 666
# 对象不能更改的属性,所以这里其实是对象给自己封装了一个属性
print(p1) # <__main__.Person object at 0x0000025E6C038C88>
p1.eat() # 吃东西
# p1.eat() 会从 p1 的名称空间找eat(), 找不到就去类中找,再找不到就找父类...最后找不到抛出异常

 

# 继承又分为单继承和多继承
# 定义父类1
class Parent_Class1:
    pass

# 定义父类2
class Parent_Class2:
    pass

# 单继承,基类是Parent_Class1,派生类是 Sub_Class1
class Sub_Class1(Parent_Class1):
    pass

# 多继承
class Sub_Class2(Parent_Class1, Parent_Class2):
    pass

# 继承查看方法:
# __base__只查到从左到右继承的第一个父类
print(Sub_Class1.__bases__)  # <class '__main__.Parent_Class1'>

print(Sub_Class2.__bases__)  # (<class '__main__.Parent_Class1'>, <class '__main__.Parent_Class2'>)

# 如果没有指定基类, Python的类会默认继承 object 类,object是所有类的基类,它提供了一些常见方法(如__str__)的实现
print(Parent_Class1.__bases__)  # (<class 'object'>,)
print(Parent_Class2.__bases__)  # (<class 'object'>,)

 

# 继承的重要性——减少代码重用
# 单继承
# 如果一个实例化对象既要执行子类方法,又要执行父类方法

# 方法一;
class Animal:

    type_name = "动物类"

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

    def eat(self):
        print("吃东西")

class Person(Animal):
    # type_name = "人类"
    def __init__(self, name, sex, age, mind):
        Animal.__init__(self, name, sex, age)
        self.mind = mind

class Cat(Animal):
    def __init__(self, name, sex, age, clmib):
        Animal.__init__(self, name, sex, age)
        self.clmib = clmib

class Dog(Animal):
    def __init__(self, name, sex, age, look):
        Animal.__init__(self, name, sex, age)
        self.look = look

p1 = Person("小春", "", 28, "有思想")
print(p1.__dict__)  # {'name': '小春', 'sex': '男', 'age': 28, 'mind': '有思想'}
c1 = Cat("土豆", "", 2, "爬树")
print(c1.__dict__)  # {'name': '土豆', 'sex': '女', 'age': 2, 'clmib': '爬树'}
d1 = Dog("大嘴", "", 3, "看门")
print(d1.__dict__)  # {'name': '大嘴', 'sex': '女', 'age': 3, 'look': '看门'}


# 方法二:super
class Animal:

    type_name = "动物类"

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

    def eat(self):
        print("吃东西")

class Person(Animal):
    # type_name = "人类"
    def __init__(self, name, sex, age, mind):
        super().__init__(name, sex, age)
        self.mind = mind

    def eat(self):  # 如果都有 eat(),则要先执行父类的话,应该这样写
        super().eat()
        print("%s 吃饭" % self.name)

class Cat(Animal):
    def __init__(self, name, sex, age, clmib):
        super().__init__(name, sex, age)
        self.clmib = clmib

class Dog(Animal):
    def __init__(self, name, sex, age, look):
        super().__init__(name, sex, age)
        self.look = look

p1 = Person("小春", "", 28, "有思想")
print(p1.__dict__)  # {'name': '小春', 'sex': '男', 'age': 28, 'mind': '有思想'}
c1 = Cat("土豆", "", 2, "爬树")
print(c1.__dict__)  # {'name': '土豆', 'sex': '女', 'age': 2, 'clmib': '爬树'}
d1 = Dog("大嘴", "", 3, "看门")
print(d1.__dict__)  # {'name': '大嘴', 'sex': '女', 'age': 3, 'look': '看门'}
p1.eat()
# 吃东西
# 小春 吃饭

 

---恢复内容结束---

posted @ 2019-01-15 15:04  星满夜空  阅读(423)  评论(0编辑  收藏  举报