美文网首页
一阶段day16-01面向对象

一阶段day16-01面向对象

作者: ATM_shark | 来源:发表于2018-10-19 20:05 被阅读0次

    Python中类支持继承,并且支持多继承

    一、继承

    1、什么是继承

    父类(超类):被继承的类
    子类:继承父类的类
    继承就是让子类拥有父类的属性和方法,但父类的属性和方法不发生减少和改变
    Python中所有的类都是直接或间接的继承自object

    2、怎么继承

    class 类名(父类):
    class 类名:== class 类名(object):

    3、能继承哪些东西

    对象属性、对象方法、类的字段、类方法、静态方法都可以继承
    注意:
    如果当前类设置了slots方法,会约束当前类的对象属性,会导致当前类对象无法添加除slots方法包含属性的以外属性,
    dict方法返回的字典中只包含slots方法中的属性。
    如果父类设置了slots方法,不会约束到子类的对象属性和添加,
    但是会导致子类对象的dict方法返回属性只有除dict方法包含属性的以外属性

    class Person:
        num=67
        __slots__ = ('age')  #__slots__魔法方法,只允许该类的对象属性含有‘age’
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def eat(self,food):
            print('%s吃%s'%(self.name,food))
        @classmethod
        def show_num(cls):
            print("人类数量:%d亿" %cls.num)
        @staticmethod
        def func1():
            print("静态方法")
    
    class Student(Person):
        def score(self,score):
            self.score=score
            return self.score
    # p1=Person('老王',65) #AttributeError: 'Person' object has no attribute 'name',父类__slots__方法里包含age
    # print(p1.__dict__)
    stu1=Student('小明',12)    #添加name和age属性  子类能添加name属性
    stu1.score(65)    #添加score属性
    print(stu1.__dict__)#{'name': '小明', 'score': 65} 返回字典中无age属性,父类__slots__方法里包含age
    stu1.eat("瓦萨比")
    print(stu1.num)
    stu1.show_num()
    stu1.func1()
    

    二、重写

    继承后,子类会拥有父类的属性和方法,也可以添加属于自己的属性和方法

    1、添加新方法

    直接在子类中声明的新方法只能通过子类来使用

    class Person:
        num=13
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def eat(self,food):
            print('%s吃%s'%(self.name,food))
        @classmethod
        def get_up(cls):
            print("%d亿人起床了" %cls.num)
        @staticmethod
        def run():
            print("人在跑步")
    
    class Student(Person):
        new_num=3
        def study(self):
            print('%s学习努力'%self.name)
        @staticmethod #静态方法
        def run():   #完全重写了run()方法,子类调用的是此方法,父类不变
            print("学生在跑步")
        @classmethod  #类方法
        def get_up(cls): #部分重写get_up()方法,调用父类的功能,同时新增子类的功能
            super().get_up()  #  调用父类对应方法的功能
            print("%d亿学生也起床了" %cls.new_num)   #新写的功能
    
    # stu1=Person('小花',23)
    # stu1.study() #AttributeError: 'Person' object has no attribute 'study'
    stu2=Student('小花',23)
    stu2.study()
    

    2、重写

    a、子类继承父类的方法,在子类中去重新实现这个方法的功能——》完全重写
    b、在子类方法中通过 super().父类方法 去调用父类对应方法的功能——》部分重写

    p1=Person('老王',56)
    p1.run()     #人在跑步
    p1.get_up()  #13亿人起床了
    stu3=Student('小王',17)
    stu3.run()    #学生在跑步
    stu3.get_up()    #13亿人起床了
                     #3亿学生也起床了
    

    3、类中方法的调用过程

    类.方法(),对象.方法()
    先看当前类是否有这个方法,如果有就直接调用当前类的相应方法;
    如果当前类没有这个方法,就会去父类中查找,如果有就调用父类的相应方法;
    如果父类没有这个方法,就去父类的父类中找,依次类推直到找到为止;
    如果找到基类object还没找到相应方法,程序才会崩溃

    4、添加属性

    (1)添加字段

    直接在子类中声明新的字段

    (2)添加属性

    子类是通过继承父类的init方法来继承父类的对象属性

    class Car:
        num=10
        def __init__(self,color='red'):
            self.color=color
    
    class SportCar(Car):
        num=6   #修改父类字段默认值
        wheel_num=4    #添加新字段
        def __init__(self,color,price):
            super().__init__(color)     #调用父类init方法,并给color属性传参
            self.price=price
    
    print(Car.num)
    print(SportCar.num,SportCar.wheel_num)
    car1=Car()
    spcar1=SportCar('white',5000)
    print(car1.__dict__)
    print(spcar1.__dict__)
    

    练习:
    声明一个Person类,有属性名字、年龄和身份证号码。
    要求创建Person的对象的时候,必须给名字赋值,年龄和省份证可以赋值也可以不赋

    声明一个学生类,有属性名字、年龄、身份证号码和学号,成绩(用继承)
    要求创建学生的时候,必须给学号赋值,可以给年龄,名字赋值,不能给省份证号,和成绩赋值

    print('======================')
    class  Person:
        def __init__(self,name,age=20,person_id=123456):
            self.name=name
            self.age=age
            self.person_id=person_id
    
    class Student(Person):
        def __init__(self,stu_id,name='lw',age=12):
            super().__init__(name,age)
            self.stu_id=stu_id
            self.score=60
    p1=Person('xm')
    stu1=Student(1)
    print(p1.__dict__)
    print(stu1.__dict__)
    print('======================')
    

    三、重载

    运算符重载:通过实现类相应的魔法方法,来让类的对象支持相应的运算符

    10>20 #int类,实现 > 对应的魔法方法 gt ;实现 < 对应的魔法方法lt

    class Student:
        def __init__(self,name,age,score):
            self.name=name
            self.age=age
            self.score=score
    
        def __gt__(self, other):  #  >对应的魔法方法
            #self指的是>符号前面的值,other指的是>符号后面的值
            return self>other
        def __lt__(self, other): #   <对应的魔法方法
            #self指的是<符号前面的值,other指的是<符号后面的值
            return self<other
        def __mul__(self, other):   #* 对应的魔法方法
            result=[]
            for _ in range(other):
                result.append(self)
            return result
        def __repr__(self):
            return str(self.__dict__)
    
    stu1=Student('aa',18,87)
    stu2=Student('bb',17,80)
    print(stu1.age > stu2.age)    #True
    print(stu1.score<stu2.score)   #False
    print(stu1*3)   #[{'name': 'aa', 'age': 18, 'score': 87}, {'name': 'aa', 'age': 18, 'score': 87}, {'name': 'aa', 'age': 18, 'score': 87}]
    

    四、内存管理机制

    Python中的内存管理——》自动管理——》垃圾回收机制
    内存结构中分栈区间和堆区间,栈区间中内存是系统自动开启自动释放。堆区间的内存需要手动申请手动释放。
    目前绝大多数编程语言,都提供了一套属于自己的关于堆中的内存的管理方案——》Python中垃圾回收机制是用来管理堆中的内存的释放
    Python中的数据都是存在堆中的,数据的地址都是在栈区间。(堆数据,栈地址)
    1、内存开辟
    Python中将值赋给变量时,会先在堆中开辟空间将数据存储起来,然后将数据对应的地址赋值给栈区间的变量。
    但如果数据是数字(int或者float)和字符串(str),会先在缓存区查看这个数据之前是否已经创建过,
    如果没有就去开辟空间存储数据,返回数据地址给变量;如果之前创建过这个数据就会直接将这个数据的地址返回给变量
    2、内存释放——》垃圾回收机制
    系统每个一段时间,就会去检测当前程序中所有的对象的引用计数值是否为0,如果对象的引用计数是0,对象对应的内存就会被销毁。
    每个对象都有引用计数属性,用来存储当前对象被引用的次数。可以通过sys模块中的getrefcount去获取一个对象的引用计数值。
    (1)增加引用计数次数——》
    (2)减少引用计数次数——》删除储存对象地址的变量;修改存储对象地址变量的值

    from sys import getrefcount
    a=[1,2,3,4,5,6]  
    b=a   
    d=a.copy()  
    c=[a,b]  
    print(getrefcount(a))  #5   4+1
    print(getrefcount(d))  #2   1+1
    

    相关文章

      网友评论

          本文标题:一阶段day16-01面向对象

          本文链接:https://www.haomeiwen.com/subject/kspuzftx.html