Python的析构方法,单继承,多继承,继承的传递,重写与调用父类方法,多态,类属性和实例属性,类方法和静态方法

Day10新手小白学python

第十节 Python的析构方法,单继承,多继承,继承的传递,重写与调用父类方法,多态,类属性和实例属性,类方法和静态方法。


目录

Day10新手小白学python

前言

一、析构方法

二、单继承

三、多继承

四、继承的传递

五、重写父类方法

六、调用父类方法

七、多态

八、类属性和实例属性

九、类方法和静态方法

总结


前言

本文介绍了Python的析构方法,单继承,多继承,继承的传递,重写与调用父类方法,多态,类属性和实例属性,类方法和静态方法


一、析构方法

析构方法:当一个对象被删除或者被销毁时,python解释器会默认调用该方法删除该对象,该对象一经删除便不能使用,这个方法为__del__()方法

当整个程序脚本执行完毕后会自动调用__del__方法;当对像被手动销毁时也会自动调用 __del__ 方法;析构函数一般用于资源回收,利用__del__方法销毁对象回收内存等资源

class Animal:
    def __init__(self,name):
        self.name=name
        print('这是构造初始化方法')
        pass
    def __del__(self):
        # 主要的应用就是来操作对象的释放,一旦释放完毕,对象便不能使用
        print("当在某个作用域下面,没有被使用【引用】的情况下,解释器会自动化的调用此函数,来释放内存空间")
        print("这是析构方法")
        print('%s这个对象被彻底清理了,内存空间也被释放了' %self.name)
    pass
cat=Animal("猫")
del cat # 手动去清理删除对象,会执行__del__这个函数
input('程序等待中------')
# dog=Animal("金毛")

二、单继承

在python中展现面向对象的三大特征:封装、继承、多态

封装:指的是把内容封装到某个地方,便于后面的使用。他需要:把内容封装到某个地方,从另外一个地方去调用被封装的内容。对于封装来说 其实就是使用初始化init构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容

继承: 和现实生活当中的继承是一样的:也就是 子可以继承父的内容【属性和行为】(爸爸有的儿子都有,相反 儿子有的爸爸不一定有)。 所以对于面向对象的继承来说 ,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一去实现,这样就可以极大的提高效率,减少代码的重复编写,精简代码的层级结构,便于拓展。

单继承的用法:

 class 类名(父类):
      '''
       子类就可以继承父类中公共的属性和方法
      '''
     pass

class Animal:
    def eat(self):
        '''
        吃
        :return:
        '''
        print('吃饭了')
        pass
    def drink(self):
        '''
        喝
        :return:
        '''
        pass
class Dog(Animal):  # 继承Animal Animal是父类 此时Dog就是子类
    def wwj(self):
        '''
        子类独有的实现
        :return:
        '''
        print("小狗汪汪叫")
    pass
class Cat(Animal):
    def mmj(self):
        '''
        子类独有的实现
        :return:
        '''
        print("小猫喵喵叫")
    pass
d1=Dog()
d1.eat()    # 具备了吃的行为 是继承了父类的行为
d1.wwj()
c1=Cat()
c1.eat()    # 具备了吃的行为 是继承了父类的行为
c1.mmj()

三、多继承

概念:子类可以继承两个父类或多个父类

C类可以继承AB两个类, 可以将A,B中的方法继承过来,C拥有AB的方法属性

同名方法:多继承例中,如果父类A和父类B中,有一个同名的方法,那么通过子类去调用的时候,同级的先调用写在前面的那个,先把同级的调完后再依此套娃调用下一级

__mro__ 方法解析顺序:查询执行顺序,方法的执行顺序可以用mro查看。 一旦找到,则寻找过程立即中断,便不会再继续找了。

class shenxian:
    def fly(self):
        print('神仙都会飞')
        pass
class Monkey:
    def chitao(self):
        print('猴子喜欢吃桃')
        pass
class sunwukong(shenxian,Monkey):   # 孙悟空既是神仙 同时也是猴子
    pass

swk=sunwukong()
swk.chitao()
swk.fly()

# 问题是:当多个父类中存在相同方法时 应该去调用哪一个呢
class D(object):
    def eat(self):
        print('D.eat')
        pass
    pass
class C(D):
    def eat(self):
        print('C.eat')
        pass
    pass
class B(D):
    pass
class A(B,C):
    pass
a=A()
a.eat()     # 输出  C.eat
print(A.__mro__)        # 可以显示类的依此继承关系
# 在执行eat的方法时 查找方法的顺序是
# 首先到A里面去查找 如果A中没有 则继续去B中去查找 如果B中没有
# 则去C中查找 如果C类中没有 则去D类中去查找 如果还是没有找到 就会报错
# A-->B-->C-->D 也是继承的顺序

四、继承的传递

类的传递过程中,我们把父类又称为基类,子类又称为派生类,父类的属性和方法可以一级一级的传递到子类。Son类继承Father类,Father类并没有提供eat方法,但是父类又继承了Grandfather类。Son的对象调用eat方法可以正常执行,运行结果得出,Son类也继承了Granderfather类的方法。这就是继承的传递性

class GrandFather:
    def eat(self):
        print('吃的方法')
        pass
    pass
class Father(GrandFather):
    pass
class Son(Father):
    pass
son=Son()
print(Son.__mro__)
son.eat()   # 此方法是从父亲的父亲继承来的

五、重写父类方法

所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法 。为什么要重写,因为父类方法不能满足子类需要,则子类可以重写父类或者完善父类的方法。

class GrandFather:
    def eat(self):
        print('吃的方法')
        pass
    pass
class Father(GrandFather):
    def eat(self):      # 因为父类中已经存在这个方法 在这里相当于方法重写【方法覆盖】
        print('爸爸经常吃海鲜')
        pass
    pass
class Son(Father):
    pass
son=Son()
print(Son.__mro__)
son.eat()   # 输出:爸爸经常吃海鲜

六、调用父类方法

如果在子类中有一个方法需要父类的功能,并且又要添加新的功能。如果直接重写父类方法,那么就要重复写很多代码。那么这就要调用父类方法

class Dog:
    def __init__(self,name,color):
        self.name=name
        self.color=color
    def bark(self):
        print('汪汪叫')
        pass
    pass
class keji(Dog):
    def __init__(self,name,color):   # 属于重写父类的方法
        # 针对这种需求 我们就需要去调用父类的函数了
        Dog.__init__(self,name,color)  # 手动调用 调用父类的方法 执行完毕就可以具备name和color两种属性了
        # super().__init__(name,color)    # super 自动找到父类 进而调用方法 假设继承了多个父类,那么会按照顺序逐个去找,然后再调用
        # 拓展其他的属性
        self.height=50
        self.weight=20
        pass
    def __str__(self):
        return '{}的颜色是{},它的身高是{}cm,体重是{}kg'.format(self.name,self.color,self.height,self.weight)
    def bark(self):     # 属于重写父类的方法
        super().bark()      # 调用父类的方法
        print('叫的更好听')
        print(self.name)
    pass

kj=keji('柯基','白色')
kj.bark()
print(kj)

七、多态

多态:顾名思义就是多种状态、形态,就是同一种行为,对于不同的子类【对象】有不同的行为表现

要想实现多态 必须有两个前提需要遵守:1、继承:多态必须发生在父类和子类之间;2、重写: 子类重写父类的方法

多态有什么用:增加程序的灵活性,增加程序的拓展性

class Animal:
    '''
    父类【基类】
    '''
    def Say_who(self):
        print('我是一个动物')
        pass
    pass
class Duck(Animal):
    '''
    子类【派生类】 鸭子
    '''
    def Say_who(self):
        '''
        在这里重写父类的方法
        :return:
        '''
        print('我是一只鸭子')
        pass
    pass
class Dog(Animal):
    '''
    子类【派生类】 小狗
    '''
    def Say_who(self):
        '''
        在这里重写父类的方法
        :return:
        '''
        print('我是一只小狗')
        pass
    pass
class Cat(Animal):
    '''
    子类【派生类】 小猫
    '''
    def Say_who(self):
        '''
        在这里重写父类的方法
        :return:
        '''
        print('我是一只小猫')
        pass
    pass
class Bird(Animal):
    '''
    新增鸟类 无需修改原来的代码
    '''
    def Say_who(self):
        print('我是一只鸟')
        pass
    pass
class People:
    def Say_who(self):
        print('我是人类')
        pass
    pass
class Student(People):
    def Say_who(self):
        print('我是学生')
        pass
    pass

#多态统一执行的方法:定义一个函数,拥有同一种行为的不同对象的循环调用即可,但该对象必须是重写父类的子类
def commonInvoke(obj):
    '''
    统一调用的方法
    :param obj: 对象的实例
    :return:
    '''
    obj.Say_who()

# duck1=Duck()
# duck1.Say_who()
# dog1=Dog()
# dog1.Say_who()
# cat1=Cat()
# cat1.Say_who()

listObj=[Duck(),Dog(),Cat(),Bird(),Student()]
for item in listObj:
    '''
    循环调用函数
    '''
    commonInvoke(item)
#输出结果:
# 我是一只鸭子
# 我是一只小狗
# 我是一只小猫
# 我是一只鸟
# 我是学生

八、类属性和实例属性

类属性:就是类对象所拥有的属性,它被所有类对象的实例对象所共有,类对象和实例对象可以访问

实例属性:实例对象所拥有的属性,只能通过实例对象访问

如果需要在类外修改类属性必须通过类对象引用然后进行修改。

# 属性:类属性和实例属性
# 类属性: 类对象所拥有的属性
class Student:
    name='李明'   # 属于类属性  就是student类对象所拥有的
    def __init__(self,age):
        self.age=age    # 实例属性
        pass
    pass
lm=Student(20)
print(lm.name)  # 通过实例对象去访问类属性  首先访问类的实例对象即__init__中的内容,再访问类对象中的类属性
lm.name='刘德华'   # 通过实例对象可以对类属性进行修改吗? 不可以
print(lm.name)  #李明的输出结果是刘德华 但小花的输出结果仍是李明  它是给李明这个对象追加了一个新的属性
print(lm.age)   # 通过实例对象去访问实例属性

print('--通过类对象修改类属性--')
lm=Student(20)
Student.name='李易峰'      # 通过类对象修改类属性  因为name所拥有的权利属于类对象
print(lm.name)      # 后面所有调用的类属性 输出的名字全为李易峰

print('----xh的属性----')
xh=Student(28)
print(xh.name)
print(xh.age)
print('----通过类对象去访问name----')
print(Student.name)     # 只有类属性才可以被类对象访问使用的 类名.属性名的形式访问
# print(Student.age)     #会报错 因为实例属性不可以被类对象访问使用
# 小结
# 类属性是可以被类对象和实例对象共同访问使用的
# 实例属性只能被实例对象访问

九、类方法和静态方法

类方法:类对象所拥有的方法,需要用装饰器@classmethod来标识其为类方法。对于类方法,第一个参数必须是类对象,一般以类对象cls作为第一个参数,通过cls来引用的类对象的属性和方法,类方法可以被类对象和实例对象调用。可以通过类对象修改

.实例方法:实例方法的第一个参数必须是self,self传入的是实例对象,要与cls区分,通过这个self 可以去引用类属性或者实例属性,若存在相同名称实例属性和类属性的话,实例属性的优先级最高

静态方法:类对象所拥有的方法,需要用@staticmethod来表示静态方法。静态方法不需要任何参数。若是要引用属性的话 则可以通过类对象或者是实例对象去引用即可 

class People:
    country='China'
    # 类方法需要用classmethod来进行修饰一下
    @classmethod    # 通过classmethod标识一下,标识后就是类方法
    def get_country(cls):
        return cls.country  # 通过cls访问类属性
        pass
    @classmethod
    def change_country(cls,data):
        cls.country=data    #  在类方法中修改类属性的值
        pass

    # 静态方法需要用staticmethod来进行修饰一下
    @staticmethod
    def getData():      # 静态方法一般不带参数
        return People.country   # 通过类对象去引用类属性
        pass
    @staticmethod
    def add(x,y):
        return x+y
    pass
#--------------------静态方法的使用-------------------------------
# 带参数的静态方法
print(People.add(10,3))     # 输出13
# 通过类对象去引用静态方法
print(People.getData())     # 输出 China
# 通过实例对象去访问静态方法
E=People()
print(E.getData())  # 输出 China  注意:一般情况下,我们不会通过实例对象去访问静态方法 因为需要实例化对象会占用资源
# 为什么要使用静态方法
# 由于静态方法主要来存放逻辑性的代码,本身和类以及实例对象没有交互
# 也就是说,在静态方法中,不会涉及类中方法和属性的操作
# 数据和资源能够得到有效的充分利用

#--------------------类方法的使用-------------------------------
# 通过类对象去调用类方法
print(People.get_country())  # 输出 China
# 通过实例对象去调用类方法
P=People()
print('实例对象访问%s' %P.get_country())  # 输出 China
# 通过类方法传参,在类方法中修改类属性的值
print('---修改之后--')
People.change_country('英国')
print(People.get_country())     # 输出 英国



# 静态方法的例子  返回当前的系统时间
import time  # 引入第三方的时间模块
class TimeTest:
    def __init__(self,hour,min,second):
        self.hour=hour
        self.min = min
        self.second = second
        pass
    @staticmethod
    def showTime():
        return time.strftime('%H:%M:%S',time.localtime())
    pass
print(TimeTest.showTime())
t=TimeTest(2,10,15)
print(t.showTime())     # 没有必要通过实例化对象这种方式去访问静态方法 结果还是当地的时间


总结

本文仅仅简单介绍了Python的析构方法,单继承,多继承,继承的传递,重写与调用父类方法,多态,类属性和实例属性,类方法和静态方法

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值