• 1011 笔记


    组合

    1.什么是组合

    在一个类中以另外一个类的对象作为数据属性,称为类的组合。

    继承是一个子类是一个父类的关系,而组合则是一个类有另一个类的关系。

    组合就是一个类中使用到另一个类,从而把几个类拼到一起。组合的功能也是为了减少重复代码。

    2.为什么要使用组合

    组合的目的和继承一样,为了减少代码冗余

    3.如何使用组合

    # 定义父类
    class people:
        def __init__(self,name,age):
            self.name = name
            self.age =age
    # 定义学生类
    class teach(people):
        def __init__(self,name,age):
            super().__init__(name,age)
    # 定义老师类
    class student(people):
        def __init__(self,name,age):
            super().__init__(name,age)
    
    # 定义一个日期类
    class Data:
        def __init__(self,n,y,d):
            self.n = n
            self.y = y
            self.d = d
        def dayin(self):
            print(f'''
            ===打印年月日===
            年:{self.n}
            月:{self.y}
            日:{self.d}
            ''')
    # 实例化teach得到对象t
    t = teach('aaa','s')
    # 实例化Data 得到data_obj对象
    data_obj = Data(1999,10,1)
    # 将data_obj添加到对象t中,让t 可以调用Data的方法
    t.data = data_obj
    # t中有data_obj == t中可以使用Data的方法
    t.data.dayin()
    
    

    组合的练习

    '''
    选课系统需求:
        1.学生类,老师类, 学生和老师都有课程属性, 每一门课程都是一个对象.
            课程: 课程名字,课程周期,课程价钱
    
        2.学生和老师都有选择课程的功能, 还有打印所有课程的功能.
    '''
    
    
    # 定义父类
    class people:
        def __init__(self,name,age,sex):
            self.name = name
            self.age =age
            self.sex = sex
        '''定义选课的方法'''
        def add_kecheng(self,course_obj):
            '''将选择的课程传入'''
            self.course_list.append(course_obj) # self自己的list列表增加传入的课程
    
        '''得到一个老师学生的对象'''
        def print_all(self): # (传入当前的老师或学生对象)
            '''循环拿到当前对象的课程列表,列表中存放的是一个个的课程对象'''
            for course_obj in self.course_list:  # 对象的课程列表(之前追加的课程)
                '''循环每一个课程对象调用查看课程信息的方法'''
                course_obj.get_info() # 获取到的课程对象直接调用其中的打印方法
    
    # 定义老师类
    class teach(people):
        def __init__(self,name,age,sex):
            super().__init__(name,age,sex)
            # 学生选课的功能
            self.course_list = []
    
    
    # 定义学生类
    class student(people):
        def __init__(self,name,age,sex):
            super().__init__(name,age,sex)
            self.course_list = []
    
    
    # 定义一个课程类
    class Course:
        '''定义课程类的名称周期价格'''
        def __init__(self,course_name,course_period,course_prize):
            self.course_name = course_name
            self.course_period = course_period
            self.course_prize = course_prize
    
        def get_info(self):
            '''打印课程的所有信息'''
            print(f'''
            课程名称:{self.course_name}
            课程周期:{self.course_period}
            课程价格:{self.course_prize}
            ''')
    
    
    # 实例化老师与学生的对象
    tea1 = teach('老师',10,'男性')
    stu1 = student('学生',50,'男性')
    # 实例化课程的对象
    python_obj = Course('python0',6,2.0)
    linux_obj = Course('linux',6,1.0)
    
    # 通过老师学生将两门课程对象添加进teach内
    '''将整个课程信息实例化的对象传入了add_kecheng方法中
    教师类中列表course_list接受课程信息'''
    tea1.add_kecheng(python_obj)
    tea1.add_kecheng(linux_obj)
    
    '''将保存在tea1中的python获取并使用打印方法'''
    # tea1.course_list[0].get_info()
    # python_obj.get_info()
    '''直接调用查看所有的课程'''
    tea1.print_all()
    
    

    总结

    继承:

    类与类的关系,一种什么是什么的关系,子类与父类是从属关系

    组合:

    对象与对象的关系,一种什么有什么的关系,一个对象拥有另一个对象

    封装

    1.什么是封装

    把一堆属性(特征与技能)封装到一个对象中,对象可以通过.的方式获取属性

    这就是面向对象的第一个特性(好处)封装

    封装特性,可以把复杂的信息,流程,包起来,内部处理,让使用者不去关注细节

    2.为什么要封装

    目的是为了方便存取,可以通过对象.属性的方式获取属性.

    3.如何封装

    特征 : 变量 ==> 数据类型
    技能 : 函数 ==>方法属性
    

    在类内部定义一堆属性(特征与技能)

    通过 对象.属性 = 属性值 方式

    访问限制机制

    在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

    1.什么是访问限制机制

    在类内部定义,凡是以__开头的数据属性与方法属性

    都会被python内部隐藏起来,让外部不能直接访问类内部__开头的属性.

    比如  __name = 'tank'
    

    2.访问限制的目的

    一堆隐私的属性与不能被外部轻易访问的属性,可以隐藏起来,不被外部直接调用

    好处: 对重要数据获取的逻辑更加严谨,进而保证了数据的安全.

    class Foo:
        # 数据类型
        __name = 'tank'
        # 方法属性
        def __run(self):
            print('runing...')
    foo = Foo()
    print(Foo.__name)
    '''报错type object 'Foo' has no attribute '__name''''
    

    接口

    隐私属性可以挺过封装一个接口,在借口内做业务逻辑的处理,再把数据返回给调用者

    # 类在定义时执行,使用接口,隐私
    class Foo:
        # 数据类型
        __name = 'tank'
        # 方法属性
        def __run(self):
            print('runing...')
        # 接口
        def get_name(self):
            '''在接口里返回出去,类内部访问'''
            # 可以做些业务逻辑判读是否给你访问
            return self.__name
        
    foo = Foo()
    res = foo.get_name()
    print(res)
    # tank
    
    '''内部修改'''
    
        def set_name(self):
            self.__name = 'nick'
    
    foo = Foo()
    foo.set_name()
    print(foo.get_name())
     # nick
    
       
    '''访问限制判断'''
    
    class ATM:
        # 1.插卡
        def __inster_card(self):
            print('插卡')
            pass
        # 2.输入密码
        def __input_pwd(self):
            print('输入密码')
            pass
        # 3.输入取款
        def __money(self):
            print('输入金额')
            pass
        # 4.开始吐钱
        def __getmoney(self):
            print('开始吐钱')
            pass
        # 5.打印账单
        def flow(self):
            print('流水')
            pass
    
        # 取钱直接接口,封装所有的隐藏接口
        def withdraw(self):
            self.__inster_card()
            self.__input_pwd()
            self.__money()
            self.__getmoney()
            self.flow()
    
    # 实例化atm
    atm = ATM()
    atm.withdraw()
        
        
    

    注意: 在python中,不会强制限制属性的访问,类内部__开头的属性,只是做了一种变形

    class Foo:
        __name = 'tank'
            # 将__name改成 _student__name了
    print(foo._Foo__name)
    # tank
    _(父类)__(属性名)  可以直接获取
    

    property

    1.什么是property

    python中内置的装饰器,主要是给类内部的方法使用

    2.为什么要用property

    将类内部的方法def 方法名()变成def 方法,

    在对象调用某个方法是将对象.方法()变成对象.方法,看着像数据属性

    3.如何使用property

    @ property

    注意 不能对呗装饰过的方法属性修改

    '''
    计算人体bmi, bmi = 体重/身高的平方
    '''
    class People:
        def __init__(self,name,w,h):
            self.name = name
            self.w = w
            self.h = h
    
        def bmi(self):
            return self.w / (self.h ** 2 )
    
    t1 = People('wang',160,175)
    print( t1.bmi() )  
    # 加()像是动词,所以使用property 让其变为名词
    
    
    '''使用 @ property '''
    
    class People:
        def __init__(self,name,w,h):
            self.name = name
            self.w = w
            self.h = h
            
        @property   # 在想要变成普通的函数上进行调用
        def bmi(self):
            return self.w / (self.h ** 2 )
    
    t1 = People('wang',160,175)
    print( t1.bmi )  # 打印时去除括号()
    
    
    
    '''不能对被装饰过的方法进行属性修改'''
    t1.bmi = 18  
    #  会进行报错
    
    

    了解: 可以通过特殊方法来进行修改(通过修改类中属性)

    # 改
    class People:
        def __init__(self, name, w, h):
            self.name = name
            self.w = w
            self.h = h
    
        @property  # 在想要变成普通的函数上进行调用
        def bmi(self):
            return self.w / (self.h ** 2)
    
        @property
        def get_name(self):
            return self.name
    
        @get_name.setter
        def set_name(self, val):
            self.name = val
    
    
    t1 = People('wang', 160, 175)
    print(t1.get_name)
    t1.set_name = 'tank'
    print(t1.set_name)
    '''wang
    tank'''
    

    多态

    1.什么是多态

    多态指的是同一种事物的多种形态,

    就是同样的行为,后代们有多种不同的状态

    多态就是 从父亲那里继承来的同一个的行为, 孩子们各自的表现状态不一样

    2.多态的目的

    多态也称之为多态性,在程序中继承就是多态的表现形式

    多态的目的是为了, 让多种不同类型的对象, 在使用相同功能的情况下,调用同一个名字的方法名.

    父类: 定义一套统一的标准
    
    子类: 遵循父类统一的标准
    
    多态的最终目的: 统一子类编写的规范,为了让使用者更方便调用相同功能的方法
    

    3.如何实现

    1.继承父类

    在python中不会强制要求子类必须遵循父类的一套标准,所以出现了抽象类

    2.抽象类abc

    1.是什么:

    abc模块 abstract_class

    2.使用的目的

    强制子类必须遵循父类的一套标准

    3.如何使用

    import abc

    import abc
    
    class animal(metaclass=abc.ABCMeta):
    
        @abc.abstractclassmethod
        def eat(self):
            pass
    
        @abc.abstractclassmethod
        def drink(self):
            pass
    
        @abc.abstractclassmethod
        def speak(self):
            pass
    
    
    class pig(animal):
    
        def eat(self):
            pass
    
        def speak(self):
            pass
    
        def drnk(self):
            pass
    
    p = pig()
    
    # 只要继承了父类,就必须有父类的方法,可以多不能少
    

    3.鸭子类型

    1.什么是鸭子类型

    鸭子类型是编程语言中动态类型语言中的一种设计风格,一个对象的特征不是由父类决定,而是通过对象的方法决定的

    Python 不检查传入的对象的类型,这种方式通俗的被称为「鸭子类型」,比较高端的方式是叫做「隐式类型」或者「结构式类型」。

    ==例如迭代器,我们并不需要继承Iterable或者Iterator,只需要实现__iter__ 和 __next__方法的对象都可称之为迭代器,本身可以为任何类==
    

    在不知道当前对象是何物的情况下,但是你长得像鸭子,那么你就是鸭子类型

    在python中,不推荐使用抽象类强制限制子类的定义,但推荐类都遵循鸭子类型

    鸭子类型就意味着可以向任何对象发送任何的消息,语言只关心这个对象能不能接收该消息,不会去强求该对象是否为某一种特定的类型 —— 该对象的多态表现。
    

    代码

    class Animal(object):
    
        def run(self):
            print("The animal is running...")
    
    
    class Dog(Animal):
    
        def run(self):
            print('The dog is running...')
    
    
    class Cat(Animal):
    
        def run(self):
            print('The cat is running...')
    
    # 定义一个函数,只需要保证传入的有一个.run方法即可
    def makeRun(animalType):
        animalType.run()
    
    dog = Dog()
    cat = Cat()
    makeRun(dog)
    makeRun(cat)
    '''
    The dog is running...
    The cat is running...
    '''
    

    我们可以使用一个函数 makeRun() 来访问不同 Animal 子类中的相同方法。但其实对于上面的 makeRun() 函数来说,传入的参数并不一定需要是 Animal 类型的,只需要保证传入的对象有一个 run() 方法即可,如下面代码所示。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

    class Person:
        def run(self):
            print("The person is running...")
    
    person = Person()
    makeRun(person)
    # The person is running...
    
    

    而在静态语言中,如 Java ,如果需要传入 Animal 类型,则传入的对象就必须是 Animal 类型或者它的子类,否则,将无法调用 run() 方法。

    -继承

    耦合性太高,程序的可扩展性差

    -鸭子类型

    耦合性低,程序的可扩展性强

  • 相关阅读:
    Mysql支持的数据类型
    JavaScript 原型中的哲学思想
    99%的人都理解错了HTTP中GET与POST的区别
    Let's Encrypt,站点加密之旅
    说说cglib动态代理
    说说Java代理模式
    RESTful API 编写指南
    RESTful 架构风格概述
    Centos 6 搭建安装 Gitlab
    超详细的阿里字节Spring面试技术点总结(建议收藏)
  • 原文地址:https://www.cnblogs.com/fwzzz/p/11656972.html
Copyright © 2020-2023  润新知