代码改变世界

Python 继承

2018-06-12 10:06  钱先生  阅读(330)  评论(0编辑  收藏  举报

继承

  • 实现继承, 可以通过"继承"(Inheritance) 和 "组合"(Composition) 来实现. 
  • 在某些语言中, 一个子类可以继承多个基类, 但是一般情况下, 一个子类只能有一个基类, 要实现多重继承,可以通过多级继承来实现.

 

继承概念的实现方式主要有两类:

  • 实现继承
    • 实现继承是指使用基类的属性和方法而无需额外编码的能力
  • 接口继承
    • 接口继承是指仅使用属性和方法的名称, 但是子类必须提供实现的能力(子类重构父类方法)
  • 注意:
    • 在考虑使用继承时, 有一点需要注意, 两个类之间的关系应该是"属于"关系. 例如, employee是一个人, manager也是一个人. 因此这两个类都可以继承person类, 但是leg却不能继承person类.
    • 抽象类仅定义将由子类创建的一般属性和方法

 

OO开发范式大致为:

  • 划分对象 -> 抽象类 -> 将类组织成为层次化结构(继承和合成) -> 用类与实例进行设计和实现几个阶段

 

#!/usr/bin/python
# -*- coding: utf-8 -*-


# 直接继承父类方法
class Person(object):
    def talk(self):
        print("person is talking")


class BlackPerson(Person):
    pass


b = BlackPerson()
b.talk()


# 子类自己有独有方法
class Person(object):
    def talk(self):
        print("person is talking")


class BlackPerson(Person):
    def walk(self):
        print("BlackPerson is walking")


b = BlackPerson()
b.talk()
b.walk()


# 子类重写父类方法
class Person(object):
    def talk(self):
        print("person is talking")


class BlackPerson(Person):
    def talk(self):
        print("BlackPerson is talking")

    def walk(self):
        print("BlackPerson is walking")


b = BlackPerson()
b.talk()
b.walk()


# 传参
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print("person is talking")


class BlackPerson(Person):
    def talk(self):
        print("BlackPerson is talking")

    def walk(self):
        print("BlackPerson is walking")


class WhitePerson(Person):
    pass


b = BlackPerson("will smith", 30)
b.talk()
b.walk()


# 先继承,再重构
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.sex = "normal"

    def talk(self):
        print("person is talking")


class BlackPerson(Person):
    def __init__(self, name, age, strength):   # 先继承,再重构
        Person.__init__(self, name, age)  # 把子类实例传到父类(父类引用指向子类对象)
        print(self.name, self.age, self.sex)
        print(strength)

    def talk(self):
        print("BlackPerson is talking")

    def walk(self):
        print("BlackPerson is walking")


class WhitePerson(Person):
    pass


b = BlackPerson("will smith", 30, "strong")
b.talk()
b.walk()
继承

 

多继承

  • 一个子类有多个父类
#!/usr/bin/python
# -*- coding: utf-8 -*-


"""
命名规范:
1. 类名每个单词都要首字母大写
2. 类名下面要写注释
"""


class SchoolMember(object):
    """
    学校成员基类
    """
    member = 0

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

    def enroll(self):
        """
        注册
        :return:
        """
        print("just enrolled a new school memeber [%s]" % self.name)
        # self.member += 1  # 每新注册一个, 成员数加1. 这样写只是当前子类成员数加1;要想父类SchoolMember总成员数加1, 需得加到全局变量里.
        SchoolMember.member += 1

    def tell(self):
        print('------------%s info ----------' % self.name)
        for k, v in self.__dict__.items():  # __dict__方法可以打印出类的所有变量
            print("\t", k, v)
        print("end".center(33, "-"))

    def __del__(self):
        print("开除了[%s]" % self.name)
        SchoolMember.member -= 1


class School(object):
    """
    假装是另一个社团团员类(以便Teacher和Student能继承;否则School是个组织, Teacher/Student是不能继承的)
    """
    def open_branch(self, addr):
        print("opening new branch in ", addr)


class Teacher(SchoolMember, School):  # 多继承
    """
    讲师类
    """
    def __init__(self, name, age, sex, salary, course):
        # SchoolMember.__init__(self, name, age, sex)  # 继承父类变量写法1. 又称经典类写法.
        super(Teacher, self).__init__(name, age, sex)  # 继承父类变量写法2. 又称新式类写法.
        self.salary = salary
        self.course = course
        # self.enroll()  # enroll()方法在每个子类里都需要, 可以直接写在父类里

    def teaching(self):
        print("Teacher [%s] is teaching [%s]" %(self.name, self.course))


class Student(SchoolMember):
    def __init__(self,name, age, sex, course, tuition):
        SchoolMember.__init__(self, name, age, sex)
        self.course = course
        self.tuition = tuition  # fee
        # self.enroll()  # enroll()方法在每个子类里都需要, 可以直接写在父类里
        self.amount = 0

    def pay_tuition(self, amount):
        print("student [%s] has just paid [%s]" %(self.name, amount))
        self.amount += amount


t1 = Teacher("WuSir", 28, "FM", 3000, "Python")
s1 = Student("HaiTao", 38, "M", "Py15", 300000)
s2 = Student("LiChuang", 12, "M", "Py15", 11000)

print(SchoolMember.member)
t1.tell()
s1.tell()
t1.open_branch("SH")
继承进阶

 

经典类 VS 新式类

  • 写法的不同
    • 经典类继承父类变量用ParentClass.__init__;   新式类继承父类变量用super()
  • 多继承时继承顺序的不同
    • python3 没有不同, 经典类和新式类都是广度查找
    • python2 : 经典类深度查找; 新式类广度查找
#!/usr/bin/python
# -*- coding: utf-8 -*-


"""
写法不同:
1. 新式类: super
2. 经典类: ParentClass.__init__
现在都主要写新式类
"""


class Person(object):  # new style 新式类. 注: 括号里的object是一个基类.
    super(Person, self).__init__()  # init括号里写父类的全部变量名


class Person:  # classical style 经典类
    ParentClass.__init__()  # init括号里写父类的全部变量名



"""
多继承时继承顺序的区别 : 
1. python3中无区别, 都是广度查找; 
2. python2中有区别(经典类: 深度查找. 若B注掉, 不会去找C,而是直接找A.A没有才再找回C; 新式类: 广度查找.)
"""


class A(object):
    def __init__(self):
        self.n = "A"


class B(A):
    def __init__(self):
        self.n = "B"


class C(A):
    def __init__(self):
        self.n = "C"


class D(B, C):  # 广度查找: 先把B,C找完, 找不到再找A; 深度查找: 找不到B, 直接去找A而不是C, A没有才找C.
    # def __init__(self):
        # self.n = "D"  # 若打印print(d.n), 返回D. 就近原则
        pass  # 若打印print(d.n), 返回B


d = D()
print(d.n)
经典类VS新式类