首页 > 其他分享 >类的继承和派生

类的继承和派生

时间:2024-05-06 14:33:05浏览次数:16  
标签:__ name 派生 继承 self print def

【一】继承介绍

# 面向对线三大特性:继承 封装 多态
# 继承

# 【一】什么是继承
# 继承就是一种创建新类的方式,新建的类可以继承一个或多个类的属性。
# 新的类如果有自己的属性,那就叫派生

# 【二】继承的优点
# 可以继承父类的所有属性和方法,实现代码的去重

# 【三】继承方式
# 单继承:继承一个父类的子类
# 多继承:继承多个父类的子类

# class Student(School):
# 继承的类叫父类 School
# 新建的类叫子类 Student


class Person(object):
    height = 180
    weight = 50


class School(object):
    school = "清华"


# 【1】单继承:只继承一个父类
class Student(Person):
    def __init__(self, name):
        self.name = name

    def tell_me(self):
        print(f"我是 {self.name} 我身高 {self.height} 体重 {self.weight}")


stu1 = Student("dream")
stu1.tell_me()


# 【2】多继承:继承两个以上的父类
class Teacher(School, Person):
    def __init__(self, name):
        self.name = name

    def tell_me(self):
        print(f"我是 {self.name} 我身高 {self.height} 体重 {self.weight} 学校在 {self.school}")


teacher = Teacher("opp")
teacher.tell_me()

# 【3】如何查看继承的父类
# (1)查看当前继承的父类 __base__ : 如果继承多个父类,默认只打印第一个继承的父类
print(Student.__base__)  # <class '__main__.Person'>
print(Teacher.__base__)  # <class '__main__.Person'>
# (2)查看当前继承的父类们 : __bases__ 一个元组,元组中放的是所有继承的父类
print(Student.__bases__)  # (<class '__main__.Person'>,)
print(Teacher.__bases__)  # (<class '__main__.Person'>, <class '__main__.School'>)

【二】经典类和新式类

# 经典类和新式类的区别在于Python版本的不同
# 在 py3 版本之前存在两个概念 ,在之后就没有经典类的概念了,只有新式类
# 【一】什么是经典类
# 在py2中没有显示继承 object 的类或者是该类的子类都是经典类
# 【二】什么是新式类
# 在py2中显示继承 object 的类或者是该类的子类都是新式类
# 在py3之后所有的类默认都是新式类,不写m默认继承 object

【三】继承和抽象

# 什么是继承和抽象
# 继承是子类和父类之间的关系,什么是什么的概念
# 抽象相当于将某部分抽立起来再总结

# 【一】抽象
# 将不同的类。根据指定的表征总结起来归介于一个类
# 猫和狗 --> 动物
# 猪八戒 麦兜 ---> 猪
# 梅西 奥巴马 --> 人
# 猪 和 人 ---> 动物

# 【二】继承
# 基于抽象的结果,然后用语言去实现


# 【三】继承和抽象
# 继承是由少变多
# 抽象是由多变少

# 【四】在python中实现继承
# 【1】没有继承和抽象
# 有一只猫
class Cat(object):
    def speak(self):
        print(f"猫可以喵喵叫")

    def eat(self):
        print("猫可以吃饭")

    def drink(self):
        print("猫可以喝水")


# 有一只狗
class Dog(object):
    def speak(self):
        print(f"狗可以旺旺叫")

    def eat(self):
        print("狗可以吃饭")

    def drink(self):
        print("狗可以喝水")


# 【2】抽象
# 总结起来一个公共的类,可以吃喝拉撒睡
class Animal(object):
    def speak(self):
        print(f"{self.name}可以叫")

    def eat(self):
        print(f"{self.name}可以吃饭")

    def drink(self):
        print(f"{self.name}可以喝水")

# 【3】继承
# 有一只猫
class Cat(Animal):

    def __init__(self, name):
        self.name = '猫'+name


# 有一只狗
class Dog(Animal):
    def __init__(self, name):
        self.name = '狗'+name

cat_one = Cat(name='小花')
print(cat_one.speak())
dog_one = Dog(name="旺财")
print(dog_one.speak())

【四】封装后继承的属性查找顺序

【1】封装之前的属性查找顺序

class Foo:
    def f1(self):
        print('Foo.f1')

    # 【四】在父类 Foo 里面找到了 f2
    def f2(self):
        # 【五】打印 Foo.f2
        print('Foo.f2')
        # 【六】self.f1 ---> self 是谁 ?
        # 触发的是 Foo.f1 还是 Bar.f1?
        # Foo.f1 3
        # Bar.f1 2
        self.f1()


class Bar(Foo):
    # 【七】因为是 通过Bar实例化得到的对象,所以 self 就是 Bar
    def f1(self):
        # 【八】打印 Bar.f1
        print('Bar.f1')
    # 【三】Bar里面没有f2,去父类找 Foo


# 【一】类实例化得到对象
b = Bar()
# 【二】对象调用方法 f2
b.f2()
class B(object):
    def read(self):
        print(self)

class A(B):
    ...


a = A()
a.read()

b = B()
b.read()

# 哪个对象调用方法,self 就是谁

【2】有封装的时候的继承

class Foo:
    # __f1 --> _Foo__f1
    def __f1(self):
        print('Foo.f1')

    # 【4】在Foo里面找到了 f2
    def f2(self):
        # 【5】打印 Foo.f2
        print('Foo.f2')
        # 【6】
        # 没有变形的时候 self 是谁就去谁里面找
        # 但是变形之后 就只能在自己的类里面找,没办跳到别的类里面
        # Foo.f1 2
        # Bar.f1 3
        self.__f1()


class Bar(Foo):
    # 【3】没有f2. 去 Foo
    def __f1(self):
        print('Bar.f1')


# 【1】
b = Bar()
# 【2】
b.f2()

【3】总结

# 如果属性不封装的情况下,谁实例化得到的self 就去谁里面找
# 如果属性封装的情况下 , 谁实例化得到的self 无效,只能在当前所在的类的民称空间里面找

【五】派生

# 派生是指,子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法

【1】子类继承父类的属性

class People:
    school = '清华大学'

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


class Teacher(People):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, sex, age, title):
        self.name = name
        self.sex = sex
        self.age = age
        self.title = title

    def teach(self):
        print('%s is teaching' % self.name)


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('dream', 'male', 18, '高级讲师')

print(obj.name, obj.sex, obj.age, obj.title)
# dream male 18 高级讲师

【2】继承方式一

  • 指名道姓的调用某一个类的函数
class People:
    school = '清华大学'

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


class Teacher(People):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, sex, age, title):
        # 直接调用 父类 中 的 __init__ 方法
        # 调用的是函数,因而需要传入self
        People.__init__(self, name, age, sex)
        self.title = title

    def teach(self):
        print('%s is teaching' % self.name)


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('dream', 'male', 18, '高级讲师')

print(obj.name, obj.sex, obj.age, obj.title)
# dream male 18 高级讲师

【3】继承方式二

  • 调用super()会得到一个特殊的对象
  • 该对象专门用来引用父类的属性
  • 且严格按照MRO规定的顺序向后查找
class People:
    school = '清华大学'

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


class Teacher(People):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, sex, age, title):
        # 直接调用 父类 中 的 __init__ 方法
        # 调用的是绑定方法,因此会自动传入self,但是需要传入相应的参数
        super().__init__(name, sex, age)
        self.title = title

    def teach(self):
        print('%s is teaching' % self.name)


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('dream', 'male', 18, '高级讲师')

print(obj.name, obj.sex, obj.age, obj.title)
# dream male 18 高级讲师

【六】组合

# 在一个类中以另外一个类的对象作为数据属性,称为类的组合。
class Course:
    def __init__(self, name, period, price):
        self.name = name
        self.period = period
        self.price = price

    def tell_info(self):
        print(f'当前课程名字 {self.name} 当前课程周期 {self.period} 当前课程价格 {self.price}')


class Date:
    def __init__(self, year, mon, day):
        self.year = year
        self.mon = mon
        self.day = day

    def tell_birth(self):
        print(f'当前生日 {self.year} 年 {self.mon} 月 {self.day} 日')


class People:
    school = '清华大学'

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


# Teacher类基于继承来重用People的代码
# 基于组合来重用Date类和Course类的代码
class Teacher(People):
    # 老师是人
    def __init__(self, name, sex, age, title, year, mon, day):
        super().__init__(name, age, sex)
        # 老师有生日
        self.birth = Date(year, mon, day)
        # 老师有课程,可以在实例化后,往该列表中添加Course类的对象
        self.courses = []

    def teach(self):
        print(f'当前老师正在授课 {self.name}')


python = Course('python', '3mons', 3000.0)
linux = Course('linux', '5mons', 5000.0)
teacher1 = Teacher('dream', 'male', 18, '金牌讲师', 1987, 3, 23)

# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)

# 重用Date类的功能
teacher1.birth.tell_birth()

# 重用Course类的功能
for obj in teacher1.courses:
    obj.tell_info()

# 当前生日 1987 年 3 月 23 日
# 当前课程名字 python 当前课程周期 3mons 当前课程价格 3000.0
# 当前课程名字 linux 当前课程周期 5mons 当前课程价格 5000.0

【六】组合和继承的区别

  • 组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同,

【1】继承的方式

  • 通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
  • 当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人

【2】组合的方式

  • 用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3...

标签:__,name,派生,继承,self,print,def
From: https://www.cnblogs.com/zenopan101861/p/18174972

相关文章

  • 基于Lua实现类的继承
    --参考Lua官方给的代码http://lua-users.org/wiki/ClassesAndMethodsExample学习如何基于Lua脚本实现继承和面向对象的机制。下面是测试代码。--objecttest.luarequire("INC_Class")--===========================localcAnimal=SETclass("Animal")functioncAni......
  • c++继承两个类怎么实现
    在C++中,继承两个类可以通过多重继承来实现。多重继承允许一个派生类从多个基类继承属性和方法。以下是一个继承两个类的示例:#include<iostream>//第一个基类classBase1{public:voidmethod1(){std::cout<<"Base1method1"<<std::endl;}};//......
  • TypeScript入门2:类、继承、访问修饰符
    classPerson{//实例属性id:number;name:string;age:number=18;//构造函数constructor(id:number,name:string){this.id=id;this.name=name;}//实例方法introduce():string{return`hello,Iam${this.name},and......
  • Go语言系列——Go协程、信道(channel)、缓冲信道和工作池、Select、Mutex、结构体取代类
    文章目录21-Go协程Go协程是什么?Go协程相比于线程的优势如何启动一个Go协程?启动多个Go协程22-信道(channel)什么是信道?信道的声明通过信道进行发送和接收发送与接收默认是阻塞的信道的代码示例信道的另一个示例死锁单向信道关闭信道和使用forrange遍历信道23-缓冲信......
  • C#接口、抽象类、普通类和继承(子类与父类)都有其特定的用途和场景
    在C#(以及许多其他面向对象的编程语言中),接口、抽象类、普通类和继承(子类与父类)都有其特定的用途和场景。选择使用哪种机制通常取决于你的具体需求和设计目标。不过,关于“能使用接口就不用抽象类,能使用抽象类就不用类,能用父类就不用子类”的说法,这并不完全准确,因为每种机制都有其独......
  • 解决子元素继承父元素的透明度问题
    如果想在Grid后面加上一个图片,并且想让图片有一定的透明度,可以让boder和grid并列,在boder里面添加图片,然后再在grid里面添加要表示的内容<Border.Background></Border.Background><Grid.RowDefinitions><RowDefinitionHeight="100"/><RowDefinition/></Grid.R......
  • Java面向对象03——三大特性之继承
    一、继承(extends)1.1、继承是什么继承就是Java允许我们用extends关键字,让一个类与另一个类建立起一种父子关系;被继承的类称为父类(基类、超类),继承父类的类都称为子类(派生类) ,当子类继承父类后,就可以直接使用父类公共的属性和方法了当子类继承父类后,就可以直接使用父类公共的......
  • C++ 多级继承与多重继承:代码组织与灵活性的平衡
    C++多级继承多级继承是一种面向对象编程(OOP)特性,允许一个类从多个基类继承属性和方法。它使代码更易于组织和维护,并促进代码重用。多级继承的语法在C++中,使用:符号来指定继承关系。多级继承的语法如下:classDerivedClass:publicBaseClass1,publicBaseClass2,...{......
  • python多继承构造方法参数报错
    各路大神,今天下午在学习Python3.12多继承的时候,有个构造方法一直报错,希望大家能帮忙瞅瞅,求求了~~~~~~~代码如下:点击查看代码classRectangle:def__init__(self,width,height):self.width=widthself.height=heightdefarea(self):......
  • JTCR-继承-06
    继承基础classA{inti;voidm(){//body}}classBextendsA{intk;voidn(){//body}}没有类可以成为其自身的超类(superclass)。子类不能访问超类中的private成员。超类类型变量可以引用派生自该超类的子类对象,但是使用该变量只......