• 面向对象三大特性之封装


    面向对象三大特性之封装

    一、继承json模块,并派生出新的功能

    • 继承json模块中的JSONEncoder,并派生出新的功能
    import json
    from datetime import date, datetime
    
    #在原来json模块中可序列化的数据型优先
    # print(type(datetime.now()))
    #<class 'datetime.datetime'>
    
    #json不可以变化集合,类
    
    # dict1 = {
    #     # 'time1': str(datetime.now())
    #     'time1': datetime.now()
    # }
    # res = json.dumps(dict1)
    # print(res)  #Object of type datetime is not JSON serializable
    
    #现在想要自定义一个可以被json化的类
    
    class MyJson(json.JSONEncoder):
        #datetime.now() ---->o
        def default(self, o):
            #isinstance:判断一个对象是否是一个类的实例
            if isinstance(o, datetime): #True
                return datetime.strftime(o, '&Y-%m-%d %X')
    
            else:
                return super().default(self, o)
    
    dict1 = {
        'time1': datetime.now(),
        'name': 'yafeng'
    }
    
    #指定自定义的一个MyJson 派生类
    #cls= 自定义的类
    res = json.dumps(dict1, cls=MyJson)
    print(res)
    #{"time1": "&Y-11-27 14:32:22", "name": "yafeng"}
    
    

    二、组合

    • 夺命三问
    '''
    夺命三问:
        1、什么是组合?
            组合指的是一个对象中,包含另一个或多个对象
        2、为什么要用组合?
            减少代码的冗余
        3、如何使用组合?
    
    耦合度:
        藕:莲藕---> 藕断丝连
        - 耦合度越高:程序的可扩展性越低
        - 耦合度越低:程序的可扩展性越高
    
    总结:
        - 继承:
            继承是类与类之间的关系,子类继承父类的属性与方法,子类与父类是一种'从属'关系
        - 组合:
            组合是对象与对象的关系,一个对象拥有另一个中的属性/方法,是一种什么有什么的关系
    
    '''
    
    • 用组合去实现的实例
    # #继承
    # #父类
    # class People:
    #     def __init__(self, name, age, sex, year, month, day):
    #         self.name = name
    #         self.age = age
    #         self.sex = sex
    #         self.year = year
    #         self.month = month
    #         self.day = day
    #
    #     def tell_birth(self):
    #         print(f'''
    #         =====出生年月日=====
    #             年:{self.year}
    #             月:{self.month}
    #             日:{self.day}
    #
    #         ''')
    #
    #
    # #老师类
    # class Teacher(People):
    #     def __init__(self, name, age, sex, year, month, day):
    #         super().__init__(name, age, sex, year, month, day)
    #
    # #学生类
    # class Student(People):
    #     def __init__(self, name, age, sex, year, month, day):
    #         super().__init__(name, age, sex, year, month, day)
    #
    #
    # tea1 = Teacher('tank', 18, 'male', 2001, 1, 11)
    # stu1 = Student('yafeng', 16, 'male', 2003, 12, 11)
    #
    # print(tea1.name, tea1.age, tea1.sex, tea1.year, tea1.month, tea1.day)
    # tea1.tell_birth()
    #
    # '''
    # tank 18 male 2001 1 11
    #
    #         =====出生年月日=====
    #             年:2001
    #             月:1
    #             日:11
    # '''
    # print(stu1.name, stu1.age, stu1.sex, stu1.year, stu1.month, stu1.day)
    # stu1.tell_birth()
    # '''
    # yafeng 16 male 2003 12 11
    #
    #         =====出生年月日=====
    #             年:2003
    #             月:12
    #             日:11
    #
    # '''
    
    
    #用组合去实现
    class People:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    #老师类
    class Teacher(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
    
    #学生类
    class Student(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
    
    #日期类
    class Date:
        def __init__(self, year, month, day):
            self.year = year
            self.month = month
            self.day = day
    
        def tell_birth(self):
            print(f'''
            =====出生年月日=====
                年:{self.year}
                月:{self.month}
                日:{self.day}
            ''')
    
    tea1 = Teacher('tank', 25, 'female')
    date_obj = Date('1994', 1, 11)
    #老师对象中包含一个自定义的日期对象
    tea1.date_obj = date_obj
    tea1.date_obj.tell_birth()
    '''
            =====出生年月日=====
                年:1994
                月:1
                日:11
            
    '''
    
    stu1 = Student('yafeng', 18, 'male')
    date_obj = Date('1196', 1, 30)
    
    stu1.date_obj = date_obj
    stu1.date_obj.tell_birth()
    '''
            =====出生年月日=====
                年:1196
                月:1
                日:30
            
    '''
    
    
    • 组合练习
    '''
    练习需求:
        选课系统:
            1、有学生类,老师类,学生与老师有属性'名字,年龄,性别,课程'
            2、有方法,老师与学生可以添加课程,打印学习/教授的课程
            #用组合实现
    '''
    
    
    # 父类
    class People:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        # 打印出生日期
        def tell_birth(self):
            # pass
            print(f'''
            年:{self.date_obj.year}#在后面stu1.date_obj= date_obj
            月:{self.date_obj.month}
            日:{self.date_obj.day}
            ''')
    
        # 添加课程
        def add_course(self, course_obj):
            self.course_list.append(course_obj)
    
            # pass
    
        # 打印当前课表内的所有课程信息
        def tell_all_course(self):
            # 从当前对象课程列表中取出所有的课程对象
            for couser_obj in self.course_list:
                couser_obj.tell_course_info()
    
    class Student(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
            # 学生自己的课程列表
            self.course_list = []
    
    
    class Teacher(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
            # 老师自己的教授的课程列表
            self.course_list = []
    
    
    class Date:
        def __init__(self, year, month, day):
            self.year = year
            self.month = month
            self.day = day
    
    
    # 定义一个课程类:课程有:课程名称,课程价格,课程周期
    class Course:
        def __init__(self, course_name, course_price, course_time):
            self.course_name = course_name
            self.course_price = course_price
            self.course_time = course_time
    
            # 定义打印课程方法: 只打印一个课程信息
    
        def tell_course_info(self):
            print(f'''
            =====课程信息如下=====
                课程名称:{self.course_name}
                课程价格:{self.course_price}
                课程时间:{self.course_time}
            ''')
    
    
    # 创建学生对象
    stu1 = Student('yafeng', 18, 'male')
    date_obj = Date(2001, 1, 30)
    stu1.date_obj = date_obj
    
    # 创建课程对象
    python_obj = Course('python', 66666, 6)
    go_obj = Course('go', 29998, 5)
    
    # 给当前学生对象添加课程对象
    # 添加python课程
    stu1.add_course(python_obj)
    
    # 添加go课程
    stu1.add_course(go_obj)
    
    # 当前学生打印所有课程的信息
    stu1.tell_all_course()
    
    

    三、封装

    • 封装介绍
    '''
    夺命三问
        1、什么是封装?
            封:比如一个袋子,封起来
            装:比如将一堆小猫,小狗装在袋子里
            #对象---->相当于一个袋子
            封装指的是可将一堆属性和方法。封装到对象中
    
            ps: 对象就好比一个‘袋子/容器’, 可以存放一堆属性和方法
            ps: 存不是目的,目的是为了取,可以通过‘对象.’的方式获取属性或方法
    
        2、为什么要封装?
            可以通过‘对象.’的方式‘存放/获取’属性或方法
            对象拥有‘.’的机制
            方便数据的存取
    
        3、如何封装?
            class user:
                x = 10
                def func():
                    pass
    
                obj = user()
                obj.y = 20
                obj ---->x,func,y
    
    '''
    

    四、访问限制机制

    • 访问限制机制
    '''
    夺命三问:
        1、什么是访问限制机制?
            凡是在类内部定义的属性或方法,
            以__开头的属性或方法名,都会被限制,外部不能'直接访问'该属性的原型
            ps: 看起来像是将该属性或方法隐藏起来了
    
            #python特有的
            注意:凡是在类内部定义__开头的属性或方法,都会变形为_类名__属性/方法。
    
        2、为什么要有访问限制?
            比如:将一些隐私的数据,隐藏起来,不让外部轻易获取
    
            -接口:
                可以将数据封装成一个接口,可以让用户调用接口,
                并且通过相应的逻辑,最后再将数据返回给用户
    
        3、如何实现?
    
    
    '''
    
    
    # # demo1
    # class User:
    #
    #     #__开头的属性
    #     __name = 'yafeng'   #__name变形为--->  _类名__name
    #
    #     #__开头的方法
    #     def __run(self):
    #         print('yafeng is running')
    #
    #
    # # print(User.__name)  #AttributeError: type object 'User' has no attribute '__name'
    # #不能直接访问
    #
    # obj = User()
    # print(obj._User__name)  #yafeng
    
    
    # #demo2
    # class User:
    #     #__开头的属性
    #     __name = 'yafeng'
    #     __age = 18
    #     __sex = 'male'
    #     __ID = '12345678966'
    #     __bal = 12345678910
    #
    #     def __init__(self, name, age, sex):
    #         self.__naem = name
    #         self.__age = age
    #         self.__sex = sex
    #
    #
    #     #校验接口,获取用户信息
    #     def parse_user(self, username, password):
    #         if username == 'yafeng_handsome' and password == '666':
    #             print(f'''
    #             通过验证,获取用户信息
    #             用户名:{self.__naem}
    #             用户年龄:{self.__age}
    #             用户性别:{self.__sex}
    #             用户ID:{self.__ID}
    #             用户资产:{self.__bal}
    #             ''')
    #         else:
    #             print('校验失败,无法查询用户信息!')
    #
    #     #__开头的方法
    #     def __run(self):
    #         print('yafeng is running...')
    #
    # obj = User('yafeng', 18, 'male')
    # obj.parse_user('yafeng_handsome', '666')
    # '''
    #             通过验证,获取用户信息
    #             用户名:yafeng
    #             用户年龄:18
    #             用户性别:male
    #             用户ID:12345678966
    #             用户资产:12345678910
    # '''
    #
    
    #demo3
    class ATM:
        #取钱功能
        #1、插入银行卡
        def __insert_card(self):
            print('开始插卡...')
            pass
    
        #2、输入密码
        def __input_pwd(self):
            print('输入密码...')
            pass
    
        #3、输入取款金额
        def __input_bal(self):
            print('输入取款金额...')
            pass
    
        #4、出钱
        def __output_money(self):
            print('开始吐钱...')
            pass
    
        #5、打印流水账单
        def __print_flow(self):
            print('打印流水账单...')
            pass
    
        #取款顺序接口
        def withdraw(self):
            #1、插入银行卡
            self.__insert_card()
    
            #2、输入密码
            self.__input_pwd()
    
            #3、输入取款金额
            self.__input_bal()
    
            #4、出钱
            self.__output_money()
    
            #5、打印流水账单
            self.__print_flow()
    
    atm_obj = ATM()
    atm_obj.withdraw()
    

    五、propetry

    • property的应用
    '''
    夺命三问:
        1、什么是property?
            是一个python内置的装饰器,可以装饰在'类内部的方法'上。
            可以将该方法调用方式有由---->对象.方法()----> 对象.方法
    
        2、为什么用property?
            ps:在某些场景下,调用的方法只是用来获取计算后的某个值
            ps:必须通过 对象.方法() 方式调用,让该方法看起来像动词
    
            让名词的方法,调用时更为合理
            目的是为了,迷惑调用者,调用的方法误以为是 属性
    
        3、如何用?
    '''
    
    
    #需求:计算人体BMI指数
    #公式:BMI=体重/身高的平方
    #value = weight/(height*height)
    class User:
        def __init__(self, name, height, weight):
            self.__name = name
            self.weight = weight
            self.height = height
    
        #获取BMI指数的方法
        @property
        def BMI(self):
    
            return self.weight/(self.height**2)
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self, value):
            self.__name = value
    
        @name.deleter
        def name(self):  #删除属性
            del self.__name
    
    
    
    
    
    
    user_obj = User('yafaneg', 1.77, 64)
    
    # user_obj.BMI()
    # print(user_obj.BMI())
    #20.428357113217785
    
    
    #@property以后
    print(user_obj.BMI)
    #20.428357113217785
    #注意此时不能在BMI后面加(),否则会报错
    
    # print(user_obj.BMI())
    #TypeError: 'float' object is not callable
    
    # print(user_obj.name)  #yafaneg
    #
    #
    # #修改属性
    # user_obj.name = '亚峰'
    # print(user_obj.name)  #亚峰
    
    
    #删除属性
    del user_obj.name
    print(user_obj.name)  #AttributeError: 'User' object has no attribute '_User__name'
    
    
    
  • 相关阅读:
    hashmap
    Java log
    内存映像
    Java 类加载器
    keepalived配虚拟ip(vip)的作用
    zookeeper和keepalived的区别
    Linux修改/etc/profile配置错误command is not found自救方法
    在windows上部署使用Redis
    Nginx+Tomcat安装与配置(windows版)
    Tomcat+Redis+Nginx实现session共享(Windows版)
  • 原文地址:https://www.cnblogs.com/yafeng666/p/11944513.html
Copyright © 2020-2023  润新知