美文网首页
day16、类和对象的应用 2019-01-14

day16、类和对象的应用 2019-01-14

作者: 绝世小丑 | 来源:发表于2019-01-14 21:04 被阅读0次

    一、复习

    1.类的声明

    class 类名:
    类的雷类容

    2.类的属性

    属性就是声明在类中的变量

    a.对象属性:值会因为对象的不同而不同
        声明在 init 方法中,
        self.属性 = 值
        对象.属性
    
    b.类的字段:值不会因为对象的不同而不同
        直接声明在类中
        变量名 = 值
        对象.属性
    

    3.方法

    a.对象方法:直接声明在类中,自带 self 参数,调用的时候不用传参,谁调用就指向谁
        对象.方法()
        实现函数的功能需要对象属性时
        (1) init 方法:系统创建对象的时候,系统会自动调用, 需要通过构造方法来给
    
    b.类方法:声明前加 @classmethod,自带 cls 参数,调用的时候,不用传参,谁调用就指向谁
        类.方法()
        实现函数的功能需要类的字段时
    
    c.静态方法:声明前加 @stadicmethod 没有自带参数
        类.方法()
        实现函数的功能既不需要需要对象属性,也不需要类的字段时
    

    二、私有化:

    1.属性和方法

    保护的:在外部不可以使用,可以继承
    公开的:在外部可以使用,可以继承

    2.python 的的私有化

    在 python 中,属性或者方法名前加 (--),就可以加将属性或者方法变成私有的(注意)
    私有的属性和方法只能在类的内部使用,不能在类的外面使用。

    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('人类要保护大自然!')
    
    
    def main():
        p1 = Person()
    
        print(Person.num)
        # print(Person.__num2)
    
        print(p1.name)
        # print(p1.__sex)
        print(p1._Person__sex)
    
        p1.eat('面条')
        # p1.run()
    
        Person.show_num()
        Person.func1()
    
        print(p1.__dict__)
    
    
    if __name__ == '__main__':
        main()
    

    三、getter & setter

    1.应用 getter 的场景:

    getter : 获取属性的值之前想要做一些别的事情,就给这个属性添加 getter
    setter : 给对象属性赋值之前想要做一些别的事情,就给这个属性添加 setter

    2.getter :

    第一步:申明属性时,在属性前加 ''
    第二步:声明函数 @property (函数没有除了 self 以外的参数,但是要有返回值.返回值就是获取)
    def 去掉 '
    ' 的属性名(self):
    做点别的事情
    返回属性的值
    第三步:
    在类的外部,通过对象.去掉_的属性去获取相关

    3.setter :

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

    class Person:
        def __init__(self, name=''):
            self.name = name
            self._age = 0
            self._week = 1          # 属性名前面有 _ ,使用属性的时候不要直接使用
    
        # 添加 setter
        @property
        def age(self):
            return self._age
    
        @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):
            print('---------------------------------')
            if self._week < 7:
                return '星期 %d ' % self._week
            else:
                print('星期天')
    
        @week.setter
        def week(self, value):
            self._week = value
    
    
    def main():
        p1 = Person('阿黄')
        p1.age = 23
        p1.age = 2
        print(p1.week)
        p1.week = 5
    
    
    if __name__ == '__main__':
        main()
    
    

    运行效果:

    ---------------------------------
    星期 1 
    

    四 、继承

    1.什么是继承

    一个类继承一个类,其中会产生继承者和被继承者,这里的继承者加子类,被继承者叫父类/超类;
    继承就是让子类直接拥有父类的方法和属性;

    2.怎么继承

    class 类名(父类列表)
    类的内容
    说明:

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

    3.继承能继承那些东西

    所有的属性和方法都能继承,私有的属性都可以继承
    注意:slots的值不会被继承,如果在类中给 slots 赋值后,当前类的对象不能使用 dict;但是这个类的子类对象可以使用__dict
    只是 dict 中没有从父类继承下来的属性
    如果父类没有给slots赋值,直接给子类的slots,会无效
    例如:

    class Person(object):
        num1 = 123
    
        def __init__(self, name='', age=0, sex='男'):
            self.name = name
            self.age = age
            self.sex = sex
    
        def eat(self, food):
            print(' %s 在吃 %s' % (self.name, food))
    
        @classmethod
        def show_num(cls):
            print('人类的数量为 : %s' % cls.num1)
    
    
    class Student(Person):
        pass
    
    
    def main():
        Student.num1 = 5000000
        print(Student.num1)
    
        stu = Student('阿黄')
    
        stu.eat('火锅')
    
        Student.show_num()
    
    
    if __name__ == '__main__':
        main()
    
    

    运行效果:

    5000000
     阿黄 在吃 火锅
    人类的数量为 : 5000000
    

    五、添加属性和方法

    1.添加方法

    直接在子类中声明新的方法
    子类可以使用父类的属性和方法,但是父类不能使用子类添加的属性和方法

    2.方法的重写

    在子类中重新实现父类已经拥有的方法 -----完全重写
    在重写这个函数时,需要保留父类的功能在子类中添加新的功能
    -----部分重写(在子类中通过'super().'的方式调用父类方法后添加新的代码)

    3.类中函数的调用过程

    a.

    回到函数声明的位置,先看当前类中是否有方法,如果有就直接调用当前类中的方法;,没有就去看父类中有没有这个方法,
    如果父类中也没有,就看父类的父类,以此类推,,,直到找到 object 类,如果 object 类里面也是没有,程序就报错

    b.添加类的字段
    c.添加对象属性

    对象属性其实是由 init 方法继承下来的
    例如:

    class Person(object):
        num1 = 123
    
        def __init__(self, name, sex='男'):
            self.name = name
            self.age = 3
            self.sex = sex
    
        def eat(self, food):
            print(' %s 再吃 %s' % (self.name, food))
    
        @classmethod
        def show_num(cls):
            print('人类的数量为 : %s' % cls.num1)
    
    
    class StudentPlus(Person):
        def __init__(self, sno, name=None):
            self.name = name
            self.sno = sno
            self.sex = '男'
            self.age = 3
            self.score = 90
    
    
    class Student(Person):
        def student(self):
            print('%s 在睡觉' % self.name)
    
        @classmethod
        def show_num(cls):
            print('学生的数量为: %d ' % cls.num1)
    
    
    def main():
        p1 = Person('阿黄')
        stu1 = Student('大白')
        stu1.student()
        Person.show_num()
        Student.show_num()
    
    
    if __name__ == '__main__':
        main()
    
    

    运行效果:

    大白 在睡觉
    人类的数量为 : 123
    学生的数量为: 123 
    

    六、多继承

    一个类同时继承多个类
    多继承:
    class 类名(父类1, 父类2, 父类3......)
    类的内容
    多个父类中的所有方法和字段都可以继承,只是对象属性只能继承第一个父类的
    例如:

    class Animal:
        def __init__(self, name, age=0, color='黑色'):
            self.name = name
            self.age = age
            self.color = color
    
        def func1(self):
            print('对象 方法')
    
    
    class Fly:
        def __init__(self):
            self.height = 100000
    
    
    class Bride(Animal, Fly):
        pass
    
    
    def main():
        p1 = Bride('阿黄')
        print(p1.__dict__)
        # print(p1.height)                # 报错。   AttributeError: 'Bride' object has no attribute 'height'
    
    
    if __name__ == '__main__':
        main()
    
    

    运行效果:

    {'name': '阿黄', 'age': 0, 'color': '黑色'}
    

    七、运算符的重载

    1.什么是运算符重载

    通过实现类中相应的魔法方法,来让自己的对象支持相应的运算符
    注意:python 中所有的数据类型都是类,所有的数据都是对象
    例如:

    class Student:
        def __init__(self, name='', age=0, score=0):
            self.name = name
            self.age = age
            self.score = score
    
        # 返回值就是运算结果
        def __add__(self, other):
            # 支持学生加学生
            return self.age + other.age
    
        # 大于和小于符号只需要重载一个后可以了
        def __gt__(self, other):
            return self.score > other.score
    
    
    def main():
        stu1 = Student('阿黄', 3, 50)
        stu2 = Student('阿黄', 5, 50)
        print(stu1 + stu2)              # 相当于: print(stu1.__add__(stu2))
    
    
    if __name__ == '__main__':
        main()
    
    

    运行效果:

    8
    

    八、内存管理机制

    1.数据的存储(分为栈区间和堆区间)

    栈区间:从底层来看,系统自动开辟、,释放的;一般存变量,函数的调用过程是在栈区间。
    堆区间:从底层来看,由程序员自己开辟的空间;一般存数据(python 中所有的数据都是对象)。
    从 python 的角度来看,程序员已经不需要写代码来开辟空间和释放空间了。
    变量赋值过程:现在堆区间开辟空间把数据存起来,然后将数据对应的地址存到栈区间的变量中。
    注意:数字、字符串在赋值的时候,不会直接开辟空间,会先检测之前有没有存储过这个数据,
    如果有就用之前的数据地址。

    2.内存释放(垃圾回收机制)原理:

    python 中的每一个对象在创建的时候,都有一个属性,叫'引用计数',表示当前对象的应用个数。
    判断一个对象是否销毁,就看'引用计数'是否为 0 ,为 0 就销毁,否则不销毁。

    from sys import getrefcount (获取对象的引用计数)
    例如:

    from sys import getrefcount
    
    
    def main():
        list1 = [1, 2]
        print(getrefcount(list1))  # 2
    
        # 使用不同的变量存对象地址会增加引用计数
        list2 = list1
        print(getrefcount(list1))  # 3
    
        [1, list1]
        print(getrefcount(list1))  # 3
    
        # def func1(obj):
        #     print(getrefcount(list1))
        #
        # func1(list1)
    
        print(getrefcount(list1))
    
        list1 = []
        print(getrefcount(list2))  # 2
    
        del list2
        # print(getrefcount(list2))   # UnboundLocalError
    
        # def getrefcount(obj):
        #     obj = list1
        #     获取obj的引用计数
    
        bullets = [{'x': 10, 'y': 20}, {'x': 30, 'y': 10}, {'x': 100, 'y': 200}]
        del bullets[2]
    
        bullets.pop(0)
    
    
    if __name__ == '__main__':
        main()
    
    

    运行效果:

    2
    3
    3
    3
    2
    

    相关文章

      网友评论

          本文标题:day16、类和对象的应用 2019-01-14

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