Python类(class)的那些事

Python类(class)的那些事

什么是类的继承呢?

  • 继承是一种新建类的方式

  • python中父类,子类(派生类),父类和子类只有在继承的时候才会产生

  • 继承是为了拿到父类的所有东西

    首先我们来看一个下面的函数

    # 定义一个父类Parent_Foo他的属性有,姓氏、资产、车、房子
    class Parent_Foo():
        def __init__(self,first_name,money,car,house):
            self.first_name = first_name
            self.money = money
            self.car = car
            self.house = house
        def find_wife(self):
            print(f'{self.first_name}先生找到妻子白富美')
    # 定义类就要实例化来使用
    # 显然我定义了一个pf的父类,他包括以下属性
    pf = Parent_Foo('朱'10,'tesla','汤臣一品1102')
    # 他的子类继承父类的所有属性例如:first_name,money,car,house
    class Son_Foo(Parent_Foo):
        pass
    # 实例化类
    sf = Son_Foo('朱', 10, 'tesla','汤臣一品1102')
    print(sf.first_name)
    print(sf.money)
    print(sf.car)
    print(sf.house)
    # 子类继承父类的属性,并且它里面的函数也可以调用,我们姑且当里面的函数为其特殊的技能,那么我们就得到了他都有的找妻子的技能,也可以在子类里面进行调用
    sf.find_wife()
    # 可以直接调用
    
    
    • 这里给出一个问题:为什么要继承?有什么作用

    • 他的回答也很简单:减少重复,所有的父亲都可以用这个类,减轻复杂度,少写东西

    • 不推荐使用继承!!!!(为什么?来看下面的程序)

      class Animal():
          def __init__(self,height,weight):
              self.weight = weight
              self.height = height
          def jiao(self):
              print(self.__class__.__name__,'叫')
              
      class Xingxing():
          
          def sleep(self):
              print('sleep')
      
              
      class People(Animal,Xingxing):
          def read(self):
              print(self.__class__.__name__,'读书')
              
      class Dog(Animal):
          def eat_shit(self):
              print(self.__class__.__name__,'吃屎')
      aobama = People(170,120)
      aobama.jiao()
      aobama.sleep()
      meixi = People(185,150)
      meixi.jiao()
      DOG = Dog(30,40)
      DOG.jiao()
      
      
      • 继承多个时候,功能与功能之间会混乱,顶多继承一个(不会重复写),继承后查找顺序:先自己,在类,在父类,在父类的父类
      • 另一种解释就是继承是按照顺序的,他不能平级继承和越级继承,一旦继承多个那么程序就会混乱;
      • 先把图的框架画出来,必须清晰完整

我们来看这个框架:可以看到其实我们上面的程序就是基于这个框架来编写的;

人、猪、狗都是子类、动物是父类,那么我们都可以继承父类里面的属性(height,weight)以及他的技能(jiao)

当然我们自己也有独特的技能:sleep、read、eat_shit

牢记他的顺序:查找顺序:先自己,在类,在父类,在父类的父类
在这里插入图片描述

在这里插入图片描述

类的派生

为什么有派生呢?

首先,我们来看这样的问题:

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

    def f2(self):   # self = b
        print('Foo.f2')
        self.f1()   # b.f1
class Bar(Foo):
    def f1(self):
        print('Bar.f1') 

b = Bar()
b.f2() # Foo.f2
print(b.__dict__) # b就是一个空字典{}
# 顺序:先自己,在类,在父类,在父类的父类
# 先自己没找到,然后去Foo找,有f2打印,调用f1注意这里的f1是self也就是他的传进来的b的f1
# 打印结果
Foo.f2
Bar.f1
{}
class Animal():
    def __init__(self,height,weight):
        self.weight = weight
        self.height = height
    def jiao(self):
        print(self.__class__.__name__,'叫')
        
class Xingxing():
    
    def sleep(self):
        print('sleep')

        
class People(Animal,Xingxing):
    def __init__(self,name,age):
        
        self.name = name
        self.age =age
        
    def read(self):
        print(self.__class__.__name__,'读书')
        

peo = People('mike',20) # 实例化的时候自动调用__init__
print(peo.__dict__)
# 打印结果为:
# {'name': 'mike', 'age': 20}
  • 那么我们就发现了一个尴尬的问题:那就是我们定义的People并没有继承我们父类的Animal的属性,那我们的继承就失去了意义?
    如何解决就引出了我们的派生:
  • 首先我们考虑这样的一个问题 我们在实例化的时候是不是可以这样操作
Animal.__init__(self,height,weight)# 对Animal类的__init__实例化,有init就调用,这里就是调用父类的init

那么我们就将上述代码修改为:

class Animal():
    def __init__(self,height,weight):
        self.weight = weight
        self.height = height
    def jiao(self):
        print(self.__class__.__name__,'叫')
        
class Xingxing():
    
    def sleep(self):
        print('sleep')

        
class People(Animal,Xingxing):
    def __init__(self,name,age):
        
        self.name = name
        self.age =age
        
    def read(self):
        print(self.__class__.__name__,'读书')
        
peo = People('mike',20) 
Animal.__init__(peo,180,110) # Animal.__init__(self,height,weight)
print(peo.__dict__)
# 通过在People里面添加Animal的.__init__完成我们派生的目的

既然它可以放在外面那我们是不是也可以放在里面:

怎么做呢?

# 方法一:
class Animal():
    def __init__(self,height,weight):
        self.weight = weight
        self.height = height
    def jiao(self):
        print(self.__class__.__name__,'叫')
        
class Xingxing():
    
    def sleep(self):
        print('sleep')

        
class People(Animal,Xingxing):
    def __init__(self,name,age,height,weight):
                #    'mike',20,180,110
        Animal.__init__(self,height,weight)# Animal.__init__(peo,180,110)
        self.name = name
        self.age =age
        
    def read(self):
        print(self.__class__.__name__,'读书')
peo = People('mike',20,180,110)
print(peo.__dict__)

输出结果:

{'weight': 110, 'height': 180, 'name': 'mike', 'age': 20}

这样我觉得还是不简洁,还是很繁琐,这其实和最开始的实例化一样的,那我为什么还要称为派生呢:

那么我们来看看大佬们怎么做的:

# 方法1不需要继承也能做到
# 只适用于python3,而python2只能用第一种方法
# 即:super(People,self).__init__(height,weight)
class Animal():
    def __init__(self,height,weight):
        self.weight = weight
        self.height = height
    def jiao(self):
        print(self.__class__.__name__,'叫')
        
class Xingxing():
    
    def sleep(self):
        print('sleep')

        
class People(Animal):
    def __init__(self,name,age,height,weight):
                #    'mike',20,180,110
        super().__init__(height,weight) # 别人规定的语法
        self.name = name
        self.age =age
        
    def read(self):
        print(self.__class__.__name__,'读书')
peo = People('mike',20,180,110)
print(peo.__dict__)

o_o!!!

惊呆了,原来只需要将Animal.__init__(self,height,weight)变成super().__init__(height,weight)就可以了

当然这是python3的用法,而python2就需要看这个啦super(People,self).__init__(height,weight)

浅浅总结一下吧:

  • 派生:继承父类属性的同时增加新的属性,然后使用super.__init__()

在这里插入图片描述

类的组合:组合在一起

我们来玩一个选课系统:

  • 先写框架:主要有学生、老师、管理员、课程类,那么人的父类就是People,课程可以不继承父类
    • People类
    • 学生类
    • 老师类
    • 管理员类

来看一下怎么操作的:

# 定义父类:people类
class People:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
# 学生类     
class Students(People):
    # 学生姓名,id,年龄,性别
    def __init__(self,student__id,name, age, gender):
        self.student__id = student__id # 学生特有属性id
        super().__init__(name, age, gender) # 继承父类
        
    def choose_course(self, course): # 特有技能
        print(f'{self.name}选择{course.name}成功') # 这里的self就是特指Students.name
        
# 老师类        
class Teacher(People):
    # 老师姓名,性别,级别
    
    def __init__(self, level, name, age, gender):
        self.level = level
        super().__init__(name, age, gender)
        # 老师给某某学生什么课打分,那么我们需要学生名、课程和分数
        
    def scored(self, student, course, score):
        print(f'{self.name}老师给{student.name}课程{course.name}{score}')      
        
# 管理员
class Adamin(People):
    # 创建课程
    def create_course(self, course, name, price):
        course = course(name, price)
        print(f'管理员{self.name}创建了{course}')
        return course
    
# 到这里我们发现没有课程,那么我们创建课程
class course:
    def __init__(self, name, price):
        self.name = name 
        self.price = price
        
# 实例化,类的对象
mike = Students('01', 'mike', 18, 'male')
jieke = Students('02', 'mike', 18, 'male')

# 老师
yy = Teacher('1', 'yy', '30',' male')
yyy = Teacher('2', 'yyy', '40', 'male')

# 管理员
sss = Adamin('sss',58,'male')
# 这样我们就将上面的人弄完了,但是选课是需要交互的
# 那么如何交互呢?
# 交互,学生选课,那么课程是管理员创建的,因此我们将代码修改为02版本
# 1、创建课程:把空列表python{}传到调用函数里面创建实例化对象,然后返回实例化对象python(有内容了)

# 01版本
# class Adamin(People):
#     # 创建课程
#     def create_course(self,course):
#         
#         print(f'管理员{self.name}创建了{course}')

# 修改后        
# 02版本
#     def create_course(self,course,name,price):
#         course = course(name,price)
#         print(f'管理员{self.name}创建了{course}')
#         return course


python = sss.create_course(course, 'python', 8888)# 这里course是实例化对象
linux =  sss.create_course(course, 'linux', 666)
print(python.__dict__)
print('*' * 50)
print(linux.__dict__)

# 学生选课要有课程,那么我们现在的代码呢?
# class Students(People):
#     def __init__(self,student__id,name,age,gender):
#         self.student__id = student__id
#         super().__init__(name,age,gender)
        
#     def choose_course(self,course):
#         print(f'{name}选择{course}')
# 如何做呢?
# 修改后
# class Students(People):
#     def __init__(self,student__id,name,age,gender):
#         self.student__id = student__id
#         super().__init__(name,age,gender)
        
#     def choose_course(self, course): # python 对象
#         self.course = course # 将上面创建的实例化对象传进来,就完成了,这就是组合
#         print(f'{self.name}选择{course.name}')

# 2、选课程
mike.choose_course(python)
yy.scored(mike,python,'0')
# 当然我们还可以进行input,这样的操作

输出结果:

管理员sss创建了<__main__.course object at 0x000001C5FC0B1160>
管理员sss创建了<__main__.course object at 0x000001C5FAE5D2B0>
{'name': 'python', 'price': 8888}
**************************************************
{'name': 'linux', 'price': 666}
mike选择python成功
yy老师给mike课程python打0

总结:

  1. 弄清了什么是类的继承
  2. 弄清派生的方法
  3. 弄清类的组合方法

参考链接:

类的继承 (cnblogs.com)

类的派生

类的组合

super()方法详解 _

总结:

  1. 弄清了什么是类的继承
  2. 弄清派生的方法
  3. 弄清类的组合方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值