继承、多继承、魔术方法知识点总结

一、继承:简化代码避免重复
  继承的意思相当于把父类中可以使用的方法写在自己类中一个性质

例1:创建一个人类,分男人类与女人类
  属性:姓名、年龄
  方法:吃、走 ====》公共特征
  男:方法==》上班
  女:方法==》洗衣服
class People:  # 父类,可以理解为一个较为抽象的类,具体细分由下面的子类完成
    # 公共代码放置位置
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def run(self):
        print('%s走路'%self.name)
    def eat(self):
        print('吃东西')

# 继承People类:继承的意思相当于把以上可以使用的方法写在自己的类中一个性质
class man(People):   # 男人类

    def work(self):
        print('%s上班'%self.name)
# 继承People类
class woman(People):
# class woman(man):
    def watch(self):
        print('%s洗衣服'%self.name)

# 实例化
xiaoming=man('小明',20)
xiaoming.run()
xiaoming.work()
#
xiaohua=woman('小花',19)
xiaohua.run()
xiaohua.watch()
# xiaohua.work() # 不能访问小明的方法,子类之间的方法不可以互相访问,除非woman继承man类
# __bases__查看类继承的直接父级(通过类名)
print(woman.__bases__)  # (<class '__main__.man'>,) 继承 
print(man.__bases__)  #  (<class '__main__.A'>,) 继承people  
print(People.__bases__)  # (<class 'object'>,)
# print(xiaohua.__bases__) # 错误写法

运行截图:

 例2:多继承:

  重写:当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法 

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

    def run(self):
        print('%s走路'%self.name)
    def eat(self):
        print('吃东西')

class Father(base): # 爸爸类
    def work(self):
        print('%s上班'%self.name)

    def cook(self):
        print('%s做饭好难吃'%self.name)

class Mother(base): # 妈妈类
    def watch(self):
        print('%s洗衣服' % self.name)
    def cook(self):
        print('%s做饭真好吃'%self.name)

# 如果Father在前面先继承Father类,优先级
class Son(Father,Mother):
    # 重写:当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法
    def cook(self):

        # pass
        print('%s做饭最好吃!!!'%self.name)

xiaoming=Son('小明',20)
#
xiaoming.watch()
xiaoming.work()
xiaoming.run()
xiaoming.eat()
xiaoming.cook() # Father在前面先继承
print(Son.__mro__) # 查询类继承的顺序==  调用方法的时候依次查询     object是所有类的父类

运行截图:  

 例3:重写父类方法之后,如果又需要使用父类的方法呢?

  super().money() # 如果自己的资金不够就把父类的也拿过来

     super 函数可以调用父类的方法,在父类中也可以使用super函数

  Father.cook(self) # 这样写先继承Father类===》可以理解准确性的继承

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

    def run(self):
        print('%s走路'%self.name)
    def eat(self):
        print('吃东西')

class Father(base):
    def work(self):
        print('%s上班'%self.name)

    def cook(self):
        print('%s做饭好难吃'%self.name)

    def money(self):
        print('爸爸有10万')

class Mother(base): # 多继承
    def watch(self):
        print('%s洗衣服' % self.name)
    def cook(self):
        print('%s做饭真好吃'%self.name)
    def money(self):
        print('妈妈有5万')

class Son(Mother,Father): # 哪个在前面先继承哪个类
    def cook(self): # 重写(新建一个新的类与父类方法名一样的时候),重写就不再使用父类的方法
        # pass
        super().cook() # 在使用的重写的时候再去拿父级的方法,重写了的话就使用自己的
        # super().watch()
        Father.cook(self) # 这样写先继承Father类===》可以理解准确性的继承
        print('%s做饭最好吃!!!'%self.name)
    def money(self):
        super().money() # 如果自己的资金不够就把父类的也拿过来
        Father.money(self) # 继承爸爸类
        print('我有一万!!!')

xiaoming=Son('小明',20)

xiaoming.watch()
xiaoming.work()
xiaoming.run()
xiaoming.eat()
xiaoming.cook() # Mother在前面先继承
xiaoming.money()
print(Son.__mro__) # 查询类继承的顺序==  调用方法的时候依次查询

运行截图:

 

二、魔术方法

  思考:字符串拼接的时候,字符串可以直接相加,那我们自定义的类可以实现吗?

例1:

class Rectangle:  # 英 [ˈrektæŋɡl] 长方形、矩形
    def __init__(self,length,width):
        self.length = length
        self.width = width

    def __add__(self,other):  # __add__两个实例相加的时候触发这个魔术方法
        add_length = self.length + other.length
        add_width = self.width + other.width
        return add_length,add_width

    def Area(self):
        areas = self.length * self.width
        return areas

# 实例a,b
a = Rectangle(3,4)
b=Rectangle(5,7)
print(a+b)
print(a.Area())
# 以上非重点内容,以下代码为重点内容

 运行截图:

 例2:str与repr知识点

    1.在交互模式下输出的交互信息与 直接print的信息有些不同, 背后的原理是 ?

    交互式模式使用repr方法

  2.我们该如何使用这种机制 ?

  3.类的实例可以向函数一样被调用吗?

    正常情况下,实例是不能像函数一样被调用的,要想实例能够被调用,就需要定义 __call__  方法

 

class Rectangle:  # 类名后面可以不用括号   #  class Rectangle(object):

    def __str__(self):  # 打印实例名的时候会触发(自己调用)__str__方法

        print(123)
        return '1232'  # 只可以返回字符串,必须要有return

        # return 123  # 错误写法
        # return [123] # 错误写法

    # def __repr__(self):  # 在开发时在调试的时候应用,即交互式模式下
    #
    #     return '1236666'  # 只可以返回字符串,必须要有return
    #     # print(123)  # 错误写法,必须是字符串
    def __call__(self, *args, **kwargs): # 实例名加括号会触发这个方法
        print('123111100000000000')
        return '1231111'

r = Rectangle() # 创建实例化
print(r)  # str方法
print(r.__class__)  # 查看类名
r()  # call方法
print(r())
# print(123)

运行截图:

 例3:常见的魔术方法

class Rectangle:
    '''
    对于类的注释一般写在这里,比如用户注册
    账号:
    密码:
    '''
    name='小明'
    def __init__(self,age):
        self.age=age

r = Rectangle(19) # 创建实例化
print(r.__dict__)  # 查看全部属性,返回属性和属性值键值对形式
print(r.__doc__)  # 查看对象文档,即类中(用三个引号引起来的部分)

print(Rectangle.__bases__) # 查看父级
print(Rectangle.__mro__) #  查看多继承的顺序

运行截图:

 练习题:

    定义正方形类(继承矩形类),实现类的 实例可调用,调用时打印周长;
   同时,直接 打印类实例 时能够打印出实例的面积

class Rectangle:  # 英 [ˈrektæŋɡl] 长方形、矩形
    def __init__(self,length,width):
        self.length = length
        self.width = width

    def Area(self):
        areas = self.length * self.width
        # return areas
        return '该面积为:%s'%areas

# 正方形类
class Square(Rectangle):
    # 因为正方形只需一条边,所以需要重写__init__方法,满足自身需求
    def __init__(self,width):
        self.width=width

    def __call__(self, *args, **kwargs):
       print('周长为:%s'%(self.width*4))

    def __str__(self):

        return '面积为:%s'%(self.width*self.width)

s=Square(5)
s()  # 实例调用触发 Call 方法
print(s)  # 打印实例 ===》触发str方法

运行截图:

posted @ 2023-08-31 11:00  人生努力努力努力就好  阅读(19)  评论(0编辑  收藏  举报