美文网首页
Day_16-类和对象(提升)

Day_16-类和对象(提升)

作者: 两只小猪呼噜噜_1539 | 来源:发表于2019-01-14 20:56 被阅读0次

    一、私有化

    1.属性和方法访问权限
    私有的:在类的外部不可以使用,也不可以继承
    保护的:在类的外部不可以使用,可以继承
    公开的:类的外部可以使用,可以被继承

    2.python中属性和方法的访问权限
    只有公开,但是提供了另一种私有化的方式

    2.如何私有化
    定义:在属性或者方法前加__,属性或者方法就会变为私有化
    特点:私有的属性和方法只能在类的内部使用,不能在类的外面使用
    注意
    输入时,只能在前面加__,不能在后面加__

    类的字段:可以在内部用,不能在外部用
    对象属性:可以在内部用,不能在外部用
    对象方法:可以在内部用,不能在外部用
    类方法:可以在内部用,不能在外部用
    静态方法:可以在内部用,不能在外部用

    3.python私有化原理
    在私有化的属性和方法前再加"_类名"去保存属性和方法
    外部想调用可以通过"_类名__(属性或者方法)"

    class Person:
        num = 61
        __num2 = 62
    
        def __init__(self, name='张三', age=0):
            self.name = name
            self.age = age
            self.__sex = '男'
    
        def eat(self, food):
            print(self.__sex)
            print(self.name, food)
            self.__run()
    
        def __run(self):
            print('%s在跑步' % self.name)
    
        @classmethod
        def show_num(cls):
            print('人类的数量:%d, %d' % (cls.num, cls.__num2))
    
        @staticmethod
        def func1():
            print('人类要保护大自然!')
    p1 = Person()
    print(Person.num)  # 61
    # print(Person.__num2)  # AttributeError: type object 'Person' has no attribute '__num2'
    print(p1.name)  # 61
    # print(p1.__sex)  # AttributeError: 'Person' object has no attribute '__sex'
    print(p1._Person__sex)  # 男
    p1.eat('面条')  # 张三 面条
    # p1.run()  # AttributeError: 'Person' object has no attribute 'run'
    Person.show_num()  # 人类的数量:61, 62
    Person.func1()  # 人类要保护大自然!
    print(p1.__dict__)  # {'name': '张三', 'age': 0, '_Person__sex': '男'}
    

    二、getter和setter

    1.应用场景
    getter获取对象属性的值(调用时)之前想要做点别的事情,就给这个属性添加getter
    setter给对象属性赋值(传参时)之前想要做点别的事情,就给这个属性添加setter

    2.getter
    第一步:声明属性的时候,在属性名前加_
    第二步:声明一个函数,函数名前加@property
    要求:只有self参数,必须要有函数返回值
    返回值:获取属性拿到的值
    @property
    def 去掉的属性名(self):
     做点别的事情
     (重点)返回属性的值
    第三步:在类的外部通过对象.去掉
    的属性去获取相关的属性

    3.setter
    要求:想要添加setter,必须添加getter为前提
    第一步:声明属性的时候,在属性名前加_
    第二步:声明函数
    要求:函数除了self以外还需要一个参数,没有返回值,参数代表给属性赋的值
    @去掉的属性名.setter
    def 去掉
    的属性名(self, 参数):
      做点别的事情
      给属性赋值
    第三步:在类的外部通过对象.去掉_的属性去给相关属性赋值

    class Person:
        def __init__(self, name=''):
            self.name = name
            self._age = 0
            self._week = 7    # 属性名前有_,使用属性的时候不要直接用
    
        @property
        def age(self):
            return self._age
    
        # 给age添加setter
        @age.setter
        def age(self, value):
            if not isinstance(value, int):
                raise ValueError
            if not (0 <= value <= 150):
                raise ValueError
            self._age = value
    
        # 给week添加getter
        @property
        def week(self):
            if self._week < 7:
                return '星期%d' % self._week
            else:
                return '星期天'
    
        @week.setter
        def week(self, value):
            self._week = value
    
    
    def main():
        p1 = Person('小明')
    
        # 通过不带_的属性给属性赋值实质是在调用setter对应的函数
        p1.age = 45
        p1.age = 3
    
        # 这个操作实质是在调用week函数
        # 通过不带_的属性来获取属性的值实质是在调用getter对应的函数
        print(p1.week)
        p1.week = 4
    

    三、继承

    1.什么是继承
    定义:一个类继承另外一个类,其中会产生继承者和被继承者,这里的继承者叫子类,被继承者叫父类/超类

    2.怎么继承
    class 类名(父类列表):
     类的内容

    说明
    a.python中所有的类都是直接或者间接继承基类object
    class 类名: ==> class 类名(object):
    b.python中的继承支持多继承, 父类列表中可以有多个类,多个类之间用逗号隔开

    3.继承哪些东西:
    所有的属性和方法
    注意a.__slots__的值继承后没有约束效果
    b.在类中给__slots__赋值后,当前类的对象不能使用__dict__,但是子类可以使用,只是__dict__中没有从父类继承下来的对象属性,只有子类中添加的对象属性
    c.如果父类没有给__slots__赋值,直接给子类的__slots__,无效

    class Person(object):
        num = 61
        # __slots__ = ('name', 'age', 'sex', '__face')
    
        def __init__(self,name='zhangsan', age=0, sex='男'):
            self.name = name
            self.age = age
            self.sex = sex
            self.__face = 60
    
        def eat(self, food):
            print('%s在吃%s' % (self.name, food))
    
        @classmethod
        def show_num(cls):
            print('人类的数量:%d' % cls.num)
    
    print(Student.num)  # 61
    stu = Student()
    print(stu.name)  # zhangsan
    # print(stu.__dict__)
    # print(stu.__face)
    stu.eat('海底捞')  # zhangsan
    Student.show_num()  # 人类的数量:61
    p1 = Person()
    # print(p1.__dict__)
    # p1.score = 100
    stu.score = 100
    print(stu.score)  # 100
    print(stu.__dict__)  # {'name': 'zhangsan', 'age': 0, 'sex': '男', '_Person__face': 60, 'score': 100}
    

    四、添加方法

    1.添加新的方法
    怎么声明:直接在子类中声明新的方法

    2.重写方法
    完全重写:在子类中重新声明实现父类的方法
    部分重写:保留父类的功能,在子类中添加新的功能
    如何操作:在子类方法中通过"super()."的方式调用父类方法

    3.类中函数的调用过程
    回到函数声明的位置:先看当前类中是否有方法,如果有,就直接调用当前类中的方法,没有就去看父类中是否有方法,如果父类也没有,就去找父类的父类,直到找到object类,如果还没有,就报错

    • 会一直往上找,不会往下找
    class Person(object):
        num = 61
    
        def __init__(self,name='zhangsan', age=0, sex='男'):
            self.name = name
            self.age = age
            self.sex = sex
            self.__face = 60
    
        def eat(self, food):
            print('%s在吃%s' % (self.name, food))
    
        @classmethod
        def show_num(cls):
            print('人类的数量:%d' % cls.num)
    
    
    class Student(Person):
        num2 = 100
    
        # 添加方法
        def study(self):
            print('%s在写代码' % self.name)
    
        @classmethod
        def func1(cls):
            print('我是学生类的类方法')
    
        @staticmethod
        def func2():
            print('我是学生类的静态方法')
    
        @classmethod
        def show_num(cls):
            print('学生数量:%d' % cls.num)
    
        def eat(self, food):
            super().eat(food)
            print('吃饱了')
    
    p1 = Person('张三')
    stu1 = Student('李四')
    stu1.study()  # 李四在写代码
    Student.func1()  # 我是学生类的类方法
    # 子类可以使用父类的属性和方法,但是父类不能使用子类中添加的属性和方法
    # Person.func2()
    Person.show_num()  # 61
    Student.show_num()  # 61
    stu1.eat('包子')  # 李四在吃包子 吃饱了
    print(Student.num2)  # 100
    

    五、添加属性

    1.添加类的字段
    如何声明:直接在子类中声明新的字段
    2.添加对象属性
    本质:对象属性是通过继承init方法继承下来的

    class Animal:
        def __init__(self, age):
            self.age = age
            self.color = '灰色'
    
    class Dog(Animal):
        def __init__(self, name, age):
            # 调用父类的init方法来继承父类的对象属性
            # 父类的init方法需要传参的话,需要在init加参数
            super().__init__(age)
            self.name = name
    # 情景1:直接继承不添加
    # dog1 = Dog()
    # print(dog1.age)
    dog2 = Dog('才次', 18)
    print(dog2.name)  # 才次
    # print(dog2.age)  # AttributeError: 'Dog' object has no attribute 'age'
    p1 = Student(23)
    print(p1.sex)  # 男
    

    补充:多继承

    多继承:
    class 类名(父类1, 父类2,....):
     类的内容
    特点
    1.方法:多个父类都可以继承
    2.属性:类的字段都可以继承,对象属性只能继承第一个父类

    class Animal:
        def __init__(self, name=''):
            self.name = name
            self.age = 0
            self.color = '黑色'
    
        def fun1(self):
            print('动物中的对象方法')
    
    
    class Fly:
        def __init__(self):
            self.height = 1000
    
        def func2(self):
            print('飞行类的对象方法')
    
    
    class Bird(Animal, Fly):
        pass
    
    def main():
        b1 = Bird()
        b1.fun1()  # 动物中的对象方法
        b1.func2()  # 动物中的对象方法
        print(b1.name, b1.age)
        # print(b1.height)  # 'Bird' object has no attribute 'height'
    

    六、运算符重载

    1.什么是运算符重载
    目的:通过实现类中相应的魔法方法来让当前类的对象支持相应的运算符

    注意:python中所有的数据类型都是类,所有的数据都是对象

    步骤
    第一步:找到运算符相应的魔法方法
    如何找:通过一个能支持的表达式,按ctrl键来查看
    第二步:在类中重新声明,重写相应的魔法方法

    class Student(object):
        def __init__(self, name='', age=0, score=0):
            self.name = name
            self.age = age
            self.score = score
    
        def __repr__(self):
            return '<' + str(self.__dict__)[1:-1] + '>'
    
        # 实现'+'对应的魔法方法,让两个学生对象能够进行+操作
        # self和other的关系: self+other    ==> self.__add__(other)
        # 返回值就是运算结果
        def __add__(self, other):
            # a.支持Student+Student:
            return self.age + other.age
            # b.支持Student+数字
            # return self.age + other
    
        # self * other
        # 将other当成数字
        def __mul__(self, other):
            return self.name * other
    
        # self和other都是学生对象
        # 注意:大于和小于运算符是需要重载一个就行
        def __gt__(self, other):
            return self.score > other.score
    
    stu1 = Student('小花', 18, 90)
    stu2 = Student('夏明', 20, 78)
    stu3 = Student('小红', 17, 99)
    
    # 所有类的对象都支持'=='和'!='运算
    print(stu1 == stu2)  # False
    
    print(stu1 + stu2)     # print(stu1.__add__(stu2))  # 38
    
    # print(stu1 > stu2)
    # print(stu1 < stu2)
    
    print(stu1 * 2)   # print(stu1.__mul__(2))  # 小花小花
    
    students = [stu1, stu2, stu3]
    print(students)
    students.sort()
    print(students)
    

    七、python内存管理机制

    1.数据的存储
    内存分为区间和区间
    底层:
    栈区间内存:系统自动释放和开辟
    堆区间内存:由程序员通过代码开辟和释放
    代码:手写函数melloc
    python:
    栈区间内存:系统自动开辟和释放
    堆区间内存:内存管理也已封装好,无需程序员在写代码手动释放
    python:
    栈区间:变量本身,函数调用过程(压栈)
    堆区间:所有的对象(python中一切数据皆对象)
    变量赋值过程
    堆区间:开辟空间储存数据,产生一个地址
    栈区间:变量储存数据的地址
    特殊情况:数字和字符串
    堆区间:赋值前先检测之前是否存过这个数据
    如果有,直接使用之前的地址,反之,开辟空间

    2.内存释放(垃圾回收机制)
    引用计数:每个对象都有一个属性叫引用计数,用来表示当前对象的引用计数
    如何判断一个对象是否销毁
    依据:看一个对象的引用计数是否为0,为0就
    销毁,不为0就不销毁
    getrefcount函数
    用法:getrefcount(对象)
    目的:获取对象的引用计数
    如何增加引用计数
    使用不同变量存地址(让多个变量指向一个地址)
    如何减少引用计数
    1.让变量指向其他地址(重新赋值)
    2.直接删除变量

    相关文章

      网友评论

          本文标题:Day_16-类和对象(提升)

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