zoukankan      html  css  js  c++  java
  • 面向对象

    一、概述

    1、面向过程编程
        核心是“过程”二字,过程指的是做事的步骤
        基于该思想编写程序就好比在设计一条条的流水线

        优点:复杂的问题流程化、进而简单化
        缺点:扩展性差

    2、面向对象编程
        核心是“对象”二字,对象是一个的容器(盛放相关的数据与功能)
        基于该思想编写程序就是造一个个对象/容器

        优点:扩展性强
        缺点:比起面向过程来说,加重了编程的复杂度

    大白话:面向对象编程的核心就是造对象/容器盛东西,该容器就是一个内存空间

    def choose(self):
        print('<%s:%s:%s>正在选课' %(self["stu1_name"],self["stu1_age"],self["stu1_gender"]))
    
    Student_dic={
    "school":"oldboy",
    "choose":choose
    }
    
    stu1_dic={
    
        "stu1_name":"egon",
        "stu1_age":18,
        "stu1_gender":"male",
    
    }
    
    stu2_dic={
        "stu1_name":"jack",
        "stu1_age":19,
        "stu1_gender":"female",
    }
    示例

    二、类与对象

    # 什么是类?
    # 类就是一个容器(一个内存空间),存放的是对象之间相同的数据与功能
    # 为何要有类?
    # 为了节省内存空间
    学生对象1
        数据
            学校="oldboy"
            名字="张三"
            年龄=18
            性别="male"
        功能
            选课功能
    
    学生对象2
        数据
            学校="oldboy"
            名字="李四"
            年龄=19
            性别="female"
        功能
            选课功能
    
    学生对象3
        数据
            学校="oldboy"
            名字="王五"
            年龄=23
            性别="male"
        功能
            选课功能
    
    学生类
        相同数据
            学校="oldboy"
        相同功能
            选课功能
    案例
    语法规定:先定义类,后调用类产生对象
    class Student:
        # 相同数据
        school ="oldboy"
    
        # 相同功能
        def choose(self):
            print('is choosing course')
    
        # print("====>")

    1.定义类=》把存有所有学生对象相同的数据与功能的内存空间准备好

    类体代码会在类定义阶段立即运行,所以会产生一个类的名称空间,将类体代码运行过程中
    产生的名字都丢到类的名称空间中,然后类名指向的就是类的名称空间
    print(Student.__dict__)
    print(Student.school) # Student.__dict__["school"]

    2.调用类=》产生对象

    # 调用类做的事情
    # (1)造一个对象的内存空间,并将给内存空间与类的内存空间绑定
    stu_obj1 = Student()
    stu_obj2 = Student()
    stu_obj3 = Student()

    print(stu_obj1)
    print(stu_obj2)
    print(stu_obj3)

    print(stu_obj1.__dict__)
    print(stu_obj2.__dict__)
    print(stu_obj3.__dict__)
    print(stu_obj1.school)

    3.为对象初始化自己独有的属性

    stu_obj1.name = "张三"  # stu_obj1.__dict__["name"]="张三"
    stu_obj1.age = 18  # stu_obj1.__dict__["age"]=18
    stu_obj1.gender = "male"  # stu_obj1.__dict__["gender"]="male"
    # print(stu_obj1.__dict__)
    
    stu_obj2.name = "李四"
    stu_obj2.age = 19
    stu_obj2.gender = "female"
    
    stu_obj3.name = "王五"
    stu_obj3.age = 23
    stu_obj3.gender = "male"
    

    三、__int__方法

    class Student:
        school ="oldboy"
    
        def choose(self):
            print('is choosing course')
    
    stu_obj1 = Student()
    stu_obj2 = Student()
    stu_obj3 = Student()
    
    
    # 为对象初始化自己独有的属性
    stu_obj1.name = "张三"  # stu_obj1.__dict__["name"]="张三"
    stu_obj1.age = 18  # stu_obj1.__dict__["age"]=18
    stu_obj1.gender = "male"  # stu_obj1.__dict__["gender"]="male"
    
    stu_obj2.name = "李四"
    stu_obj2.age = 19
    stu_obj2.gender = "female"
    
    stu_obj3.name = "王五"
    stu_obj3.age = 23
    stu_obj3.gender = "male"
    
    # 优化方案1:
    def init(obj,name,age,gender):
        obj.name = name
        obj.age = age
        obj.gender = gender
    
    init(stu_obj1, "张三" ,18,"male")
    init(stu_obj2, "李四" ,19,"female")
    init(stu_obj3, "王五" ,23,"male")
    
    print(stu_obj1.__dict__)
    print(stu_obj2.__dict__)
    print(stu_obj3.__dict__)
    
    # 终极解决方案:
    class Student:
        school ="oldboy"
        #            空对象,"张三",18,"male"
        def __init__(obj, name, age, gender):
            obj.name = name  # 空对象.name = "张三"
            obj.age = age  # 空对象.age = 18
            obj.gender = gender  # 空对象.gender = "male"
            # return None  # 注意!!!:不能有返回值
    
        def choose(self):
            print('is choosing course')
    范例

    1.调用类发生的事情

    # 1、先造一个空对象(空对象的本质就是一个与类的内存空间相关联的、对象的内存空间)
    # 2、触发类中的__init__函数的运行,会将(空对象"张三" ,18,"male")一起传给__init__函数,完成为对象初始化属性的操作
    # 3、将初始化好属性的对象的内存地址赋值给等号左侧的变量名stu_obj1
    stu_obj1=Student("张三" ,18,"male")
    stu_obj2=Student("李四" ,19,"female")
    stu_obj3=Student("王五" ,23,"male")
    
    print(stu_obj1.__dict__)
    print(stu_obj2.__dict__)
    print(stu_obj3.__dict__)
    

    四、类与对象的属性操作  

    class Student:
        school ="oldboy"
        n=0
    
        def __init__(obj, name, age, gender):
            Student.n+=1
            obj.name = name  # 空对象.name = "张三"
            obj.age = age  # 空对象.age = 18
            obj.gender = gender  # 空对象.gender = "male"
    
        def choose(self):
            print('is choosing course')
    
    
    stu_obj1=Student("张三" ,18,"male")
    stu_obj2=Student("李四" ,19,"female")
    stu_obj3=Student("王五" ,23,"male")
    
    print(Student.n)
    print(stu_obj1.n)
    print(stu_obj2.n)
    print(stu_obj3.n)
    

    1.对象属性操作

    1.对象的属性操作
    (1) 访问
    print(stu_obj1.name)
    print(stu_obj1.school)
    
    (2) 删除(只能清楚对象自己名称空间内的)
    del stu_obj1.name
    print(stu_obj1.__dict__)
    
    (3)新增与修改
    stu_obj1.x = 111
    print(stu_obj1.__dict__)
    stu_obj1.x = 222
    print(stu_obj1.x)
    对象的属性操作

    2.类的属性操作

    (1) 访问
    print(Student.school)
    print(Student.choose)
    (2) 删除(只能清楚类自己名称空间内的)
    del Student.school
    print(Student.__dict__)
    (3)新增与修改
    Student.xxx=111
    Student.xxx=222
    print(Student.__dict__)
    类的属性操作

    3.总结

    # 1、对象.属性:先从对象自己的内存空间找,没有则去类中查找
    # 类.属性:直接去类中查找
    stu_obj1.school = "xxx"
    print(stu_obj1.school)
    print(stu_obj2.school)
    print(stu_obj3.school)
    
    # 2、类中定义的属性类可以使用,但其实是为对象准备的
    # 类的数据属性是所有对象共享的
    print(Student.school,id(Student.school))
    Student.school="OLDBOY"
    print(stu_obj1.school,id(stu_obj1.school))
    print(stu_obj2.school,id(stu_obj2.school))
    print(stu_obj3.school,id(stu_obj3.school))
    
    # 类的函数属性
    print(Student.choose)
    print(stu_obj1.choose)
    print(stu_obj2.choose)
    print(stu_obj3.choose)
    小结

    五、绑定方法

    class Student:
        school ="oldboy"
    
        def __init__(self, name, age, gender):
            self.name = name  # 空对象.name = "张三"
            self.age = age  # 空对象.age = 18
            self.gender = gender  # 空对象.gender = "male"
    
        def choose(self):
            print('%s is choosing course' %self.name)
    
        def tell_info(self):
            print('<%s:%s:%s>' %(self.name,self.age,self.gender))
    
    stu_obj1=Student("张三" ,18,"male")
    stu_obj2=Student("李四" ,19,"female")
    stu_obj3=Student("王五" ,23,"male")
    stu_obj1.tell_info()
    stu_obj2.tell_info()
    stu_obj3.tell_info()
    # 类中定义的函数类可以访问,但是类来访问的时候就是一个普通函数,必须按照普通函数的玩法来
    print(Student.choose)
    Student.choose(stu_obj1)
    
    print(stu_obj1.choose)
    print(stu_obj2.choose)
    print(stu_obj3.choose)
    
    # 类中定义的函数其实是给对象准备的,对象来用,称之为调用绑定方法
    # 绑定方法的特殊之处在于自动传参:会将调用者当作第一个参数自动传入
    stu_obj1.choose() # choose(stu_obj1)
    stu_obj2.choose() # choose(stu_obj2)
    stu_obj3.choose() # choose(stu_obj2)
    
    
    
    # 在python3里统一了类与类型的概念
    l1=[1,2,3]  # l1=list([1,2,3])
    print(type(l1))
    print(type(stu_obj1))
    l2=[11,22]  # l1=list([1,2,3])
    
    l1.append(333)
    print(l1)
    l2.append(444)
    print(l2)
    
    list.append(l1,333)
    print(l1)
    list.append(l2,444)
    print(l2)
    

    六、三大特性之封装

    1 什么是封装
    封装=》整合

    2 为何要封装
    为了让程序的整合程度更高,进而提升程序的解耦合程度

    3 如何封装

    3.1 把装到类或对象里的属性藏起来
    (1)藏起来就是:把装进去的属性隐藏起来不让类外部访问到
    (2)为何要将属性藏起来???
    1、把数据属性藏器里的目的是:严格控制类外部使用者对属性的操作
    不想让外部直接操作属性,通过开放接口的方式外部间接操作属性,
    我们可以在接口之上附加任意控制逻辑,从而严格控制类外部使用者对属性的操作
    2、把功能属性藏起来的目的是:为了隔离复杂度

    (3)如何藏起来
    在属性前加__开头,就会将该属性隐藏起来

    注意:
    (1) 这种不是真正意义上的隐藏,仅仅只是一种变形操作
    (2) 该变形操作只在类定义阶段检查语法的时候变形一次,在此之后,新增的__开头的属性
    都不会发生变形
    (3) 该变形操作对外不内

    4.应用

    class People:
        def __init__(self,name,age,gender):
            self.__name=name
            self.age=age
            self.gender=gender
    
        def get_name(self):
            print("名字:%s" %self.__name)
    
        def set_name(self,val):
            if type(val) is not str:
                print("名字必须是str类型")
                return
            self.__name = val
    
        def del_name(self):
            print('不让删除')
    
    p=People('egon',18,'male')
    # p.__name=123123123
    # print(p.name)
    
    # p.get_name()
    # p.set_name("EGON")
    p.del_name()
    View Code

    5.示例

    class Foo:
        __x = 111  # _Foo__x = 111
    
        def __init__(self, m, n):
            self.__m = m  # self._Foo__m = m
            self.__n = n  # self._Foo__n = n
    
        def __f1(self):  # _Foo__f1
            print('from f1')
    
        def f2(self):  # self._Foo__m,self._Foo__n,self._Foo__x
            print(self.__m,self.__n,self.__x)
    
    print(Foo.__x)
    print(Foo.__f1)
    print(Foo.__dict__)
    print(Foo._Foo__x)
    print(Foo._Foo__f1)
    
    obj1=Foo(666,777)
    print(obj1._Foo__x)
    print(obj1._Foo__f1)
    
    print(obj1.__dict__)
    print(obj1._Foo__m)
    print(obj1._Foo__n)
    
    Foo.__zzz=1111
    print(Foo.__dict__)
    print(Foo.__zzz)
    
    obj1=Foo(666,777)
    obj1.__yyy=222
    print(obj1.__dict__)
    
    obj1.f2()
    示例

    七、property装饰器

    1.property基本使用

    class People:
        def __init__(self, name, height, weight):
            self.name = name
            self.height = height
            self.weight = weight
    
        @property
        def bmi(self):
            return self.weight / (self.height ** 2)
    
    p = People('egon', 1.8, 70)
    # print(p.bmi())
    # p.height=1.90
    # print(p.bmi)
    基本应用

    2.升级应用

    class People:
        def __init__(self,name):
            self.__name=name
    
        @property
        def name(self):  # get
            return "名字:%s" %self.__name
    
        @name.setter
        def name(self,val):  # set
            if type(val) is not str:
                print("名字必须是str类型")
                return
            self.__name = val
    
        @name.deleter
        def name(self):  # del
            print('不让删除')
    
    p=People('egon')
    
    print(p.name)
    p.name=123
    del p.name
    print(p.name)
    升级应用

    3.示例

    class People:
        def __init__(self,name):
            self.__name=name
    
        def get_name(self):  # get
            return "名字:%s" %self.__name
    
        def set_name(self,val):  # set
            if type(val) is not str:
                print("名字必须是str类型")
                return
            self.__name = val
    
        def del_name(self):  # del
            print('不让删除')
    
        name = property(get_name,set_name,del_name)
    
    p=People('egon')
    示例

    八、三大特性之继承

    1 什么是继承?
    继承是一种新建子类的方式,新建的类称之为子类,被继承的类称之为父类、基类、超类
    继承的特点:子类会遗传父类的所有属性

    2 为何要继承
    类存在的意义是为了解决对象与对象之间的冗余问题
    而继承的意义是为了解决类与类之间冗余问题

    继承体现的一种耦合思想,于扩展性的增强无益

    3 如何继承
    语法:python支持单继承与多继承

    单继承: 一个子类只能继承一个父类
    多继承: 一个子类可以同时继承多个父类

    ps:继承表达的是一个is-a的关系
    单继承符合is-a的关系,可以让继承结构相对简单一点

    而多继承不符合is-a的关系,盲目使用多继承会加大继承结构的复杂度,所以继承的正确打开方式是Mixins机制
    class Parent1:
        pass
    
    class Parent2:
        pass
    
    class Sub1(Parent1):
        pass
    
    class Sub2(Parent1,Parent2):
        pass
    
    
    print(Sub1.__bases__)
    print(Sub2.__bases__)
    View Code
    class Student:
        school = "oldboy"
    
        def __init__(self, name, age, gender,stu_id):
            self.name = name
            self.age = age
            self.gender = gender
    
            self.stu_id = stu_id
    
        def choose(self):
            print('is choosing course')
    
    
    class Teacher:
        school = "oldboy"
    
        def __init__(self, name, age, gender,level,salary):
            self.name = name
            self.age = age
            self.gender = gender
    
            self.level = level
            self.salary = salary
    
        def set_score(self, stu_obj, num):
            stu_obj.score = num
            print("老师<%s>给学生<%s>打了 %s 分" %(self.name,stu_obj.name,num))
    
    stu_obj1=Student("tom",18,'male',3536)
    tea_obj1=Teacher("egon",18,'male',10,3000)
    
    # tea_obj1.set_score(stu_obj1,60)
    # print(stu_obj1.score)
    案例1
    # 如何在子类派生的新方法中重父类的功能
    # 方案一:指名道姓地调用某一个类的函数,不依赖于继承
    class People:
        school = "oldboy"
        #            空对象,"tom",18,'male'
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    class Student(People):
        #            空对象,"tom",18,'male',3536
        def __init__(self,name,age,gender,stu_id):
            People.__init__(self,name,age,gender)
    
            self.stu_id=stu_id
    
        def choose(self):
            print('is choosing course')
    
    class Teacher(People):
        def __init__(self, name, age, gender,level,salary):
            People.__init__(self,name,age,gender)
    
            self.level = level
            self.salary = salary
    
        def set_score(self, stu_obj, num):
            stu_obj.score = num
            print("老师<%s>给学生<%s>打了 %s 分" %(self.name,stu_obj.name,num))
    
    stu_obj1=Student("tom",18,'male',3536)
    tea_obj1=Teacher("egon",18,'male',10,3000)
    
    print(stu_obj1.__dict__)
    print(tea_obj1.__dict__)
    案例2

    九、多继承

    coding:utf-8
    在python中,针对每一个类python解释器都会基于c3算法为其计算出一个MRO列表
    ps: 在python中有新式类与经典类之分
    新式类:但凡是继承了object类的子类,以及该子类的子子孙孙类都是新式类
    经典类:没有继承object类的子类,以及该子类的子子孙孙类都是经典类
    注意:在python3中,如果一个子类没有继承任何类,那么python会让其默认继承object类
    所以说,只有在python2中才存在经典类

    1.由谁引发的属性查找,就参照谁的MRO列表

    class E:
        def test(self):
            print('from E')
    
    
    class F:
        def test(self):
            print('from F')
    
    
    class B(E):
        def test(self):
            print('from B')
    
    
    class C(F):
        def test(self):
            print('from C')
    
    
    class D:
        def test(self):
            print('from D')
    
    
    class A(B, C, D):
        # def test(self):
        #     print('from A')
        pass
    
    
    print(A.mro())
    
    
    '''
    [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>]
    '''
    View Code

    2.菱形继承:一个子类继承的多个父类汇聚到一个非object类

    新式类与经典类关于属性的查找不一样
    (1)新式类:广度优先
    (2)经典类:深度优先
    class G: # 在python2中,未继承object的类及其子类,都是经典类
        # def test(self):
        #     print('from G')
        pass
    
    class E(G):
        # def test(self):
        #     print('from E')
        pass
    
    class F(G):
        def test(self):
            print('from F')
    
    class B(E):
        # def test(self):
        #     print('from B')
        pass
    
    class C(F):
        def test(self):
            print('from C')
    
    class D(G):
        def test(self):
            print('from D')
    
    # print(D.mro())
    class A(B,C,D):
        # def test(self):
        #     print('from A')
        pass
    
    obj = A()
    # print(A.mro())
    obj.test()
    View Code

    十、属性的查找

    在单继承背景下的属性查找:
    1、obj.x
    对象=》对象的类=》父类=》父父类。。。

    2、类名.x
    当前类=》父类=》父父类。。。
    class Foo:
        def f1(self):
            print("Foo.f1")
    
        def f2(self):
            print('Foo.f2')
            self.f1()  # obj.f1()
    
    class Sub(Foo):
        def f1(self):
            print("Sub.f1")
    
    obj=Sub()
    obj.f2()
    """
    Foo.f2
    Sub.f1
    示例1
    class Foo:
        def __f1(self):  # _Foo__f1
            print("Foo.f1")
    
        def f2(self):
            print('Foo.f2')
            self.__f1()  # self._Foo__f1
    
    class Sub(Foo):
        def __f1(self):  # _Sub__f1
            print("Sub.f1")
    
    obj=Sub()
    obj.f2()
    """
    Foo.f2
    Sub.f1
    """
    示例2

    十一、supper方法

    如何在子类派生的新方法中重父类的功能
    方案一:指名道姓地调用某一个类的函数,不依赖于继承
    方案二:super()会返回一个特殊的对象,super().x该对象会参照当前类的mro列表去父类里找,严格依赖继承
    class People:
        school = "oldboy"
        #            空对象,"tom",18,'male'
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def tell_info(self):
            print("名字:%s" %self.name)
            print("年龄:%s" %self.age)
            print("性别:%s" %self.gender)
    
    class Student(People):
        #            空对象,"tom",18,'male',3536
        def __init__(self,name,age,gender,stu_id):
            # People.__init__(self,name,age,gender)
            # super(Student,self).__init__(name,age,gender)  # 在python2中
            super().__init__(name,age,gender)  # 在python2中
    
            self.stu_id=stu_id
    
        def choose(self):
            print('is choosing course')
    
        def tell_info(self):
            print("学号:%s" %self.stu_id)
            super().tell_info()
    
    class Teacher(People):
        def __init__(self, name, age, gender,level,salary):
            # People.__init__(self,name,age,gender)
            super().__init__(name,age,gender)  # 在python2中
    
            self.level = level
            self.salary = salary
    
        def set_score(self, stu_obj, num):
            stu_obj.score = num
            print("老师<%s>给学生<%s>打了 %s 分" %(self.name,stu_obj.name,num))
    
    stu_obj1=Student("tom",18,'male',3536)
    tea_obj1=Teacher("egon",18,'male',10,3000)
    
    # print(stu_obj1.__dict__)
    # print(tea_obj1.__dict__)
    
    # stu_obj1.tell_info()
    # tea_obj1.tell_info()
    
    
    class A:
        def test(self):
            super().test() # 参照属性发起者的mro,去父类里找属性
    
    class B:
        def test(self):
            print('from B')
    
    class C(A,B):
        pass
    
    # obj=C()
    # obj.test()
    # print(C.mro())
    
    obj=A()
    print(A.mro())
    obj.test()
    View Code
     
  • 相关阅读:
    Best Time to Buy and Sell Stock II
    Subsets II
    Subsets I
    Combinations
    Permutation Sequence
    Next Permutation
    Anagrams
    Combination-Sum II
    Combination-Sum I
    Permutations II
  • 原文地址:https://www.cnblogs.com/datatool/p/13592119.html
Copyright © 2011-2022 走看看