Python学习笔记--面向对象--基础

1.面向对象和面向过程的区别是?

  • 面向过程:

    • 把问题,拆解性小的流程。

    • 优点是:把复杂问题,流程化后简单了。

    • 缺点是:扩展性差。
  • 面向对象:

    • 优点是:扩展性强。

    • 缺点是:将编程的复杂性变大。

 2.面向对象编程,是什么?

  • 核心是对象二字,那什么是对象?

  • 对象是一个概念

    • 是一个国外翻译过来的概念。
  • 对象是一个容器

    • 函数是一个容器,盛放功能的。
    • 对象也是一种容器,盛放数据+功能的。
  • 基于面向对象的编程思想,就是创造一个个容器,来梳理代码的。

    • 同样,面向过程也是创造一个个函数,来梳理代码的。

3.面向对象可以比喻房子里的什么东西,来帮助理解?

  • 面向过程(功能)

    • 散落的木板 ==》 书架

    • 冰箱零件 ==》 冰箱
  • 面向对象(数据+功能)

    • 书(数据)
      • 书在地上,在厕所,在厨房 ==》书在书架上。【数据+功能】
    • 大蒜(数据)
      • 大蒜在地上,在卧室... ==》大蒜在冰箱里。【数据+功能】
    • 韭菜(数据)
      • 韭菜在地上,在客厅... ==》 韭菜在冰箱里。【数据+功能】
  • 面向对象是一种归类。

    • 原则是:把相关的放在一起。
      • 比如,厨房这个容器。(对象)
        • 盛放了数据【葱,姜,蒜,鸡蛋,韭菜,调味料】
        • 盛放了功能【冰箱,电饭锅,微波炉】
  • 冰箱这个容器到底是函数还是对象?

    • 冰箱没有放任何数据的话

      • 是一个函数。
      • 它就是由一堆零件组成的。
    • 冰箱盛放了数据的话

      • 是一个对象。
      • 它由零件组成的功能+盛放的数据【葱,姜,蒜,韭菜,黄瓜...】
  • 如何区分,容器是函数还是对象?

    • 关键在于是否承载了数据。

 

4.谈谈我理解的面向对象。

  • 优点:扩展性好。
  • 缺点,需要进一步整理,复杂度高了。
    • 比如,我收拾房间。我要把书放在书架上。
    • 我首先要买个书架子,快递发给我一套木板,一堆螺丝钉,一把螺丝刀。
    • 我把这些东西组装起来,形成一个书架【功能】,功能性就是实现了。也就是函数实现了。
    • 现在又要把,书放到书架上,我这个书架有5层,我书有人文的,自然的,历史的,IT的。
    • 还有书看过的,没看过的,那些我判断是使用频率高的书籍,哪些是频率低的,把频率高的放在中间3层,4层,频率低的放在1层2层5层。
    • 我根据这些原则,把这个书【数据】放在一起。这个过程,就完成了对象的概念。同样,我相比起函数,付出了更多的时间和精力,复杂性相比之前的函数,确实提高。同样的好处是,我更方便使用这个书架,每个书的位置,都有了一定的原则(索引位置)。找起来更方便了。 

5.最能体现面向对象的扩展性强的是?

  • 封装。

    • 《封装》最能体现,但像 《继承》,反而与扩展性强是相违背的。

 6.面向对象的演绎

  • 原来的

    • # ============数据跟功能分开==============
      name = "liqi"
      age = 18
      gender = "male"
      
      def tell_info():
          print(f"名字是{name},年龄是{age},性别是{gender}")
      
      tell_info()
      # =====================================

       

  • 收拾一下

    • 把数据放到一起
    • # 把数据放到一个容器(字典里)
      def tell_info(student):
          print(f"学生的名字是{student['name']},年龄是{student['age']},性别是{student['gender']}")
      
      student = {
          "name": "liqi",
          "age": 18,
          "gender": "male",
          "tell_info": tell_info,
      }
      student["tell_info"](student)
      # 把数据由传3个,变为只传递1个
      # 上面这也是一种面向对象的思想
      # =====================================

       

  • 再收拾一下

    • 把功能也放进去
    • # # 尝试把函数的功能也放进去。(下面是的伪代码,不能运行)
      student = {
          "name": "liqi",
          "age": 18,
          "gender": "male",
          "tell_info": tell_info,
      
          def tell_info(student):
              print(f"学生的名字是{student['name']},年龄是{student['age']},性别是{student['gender']}")
      }
      student["tell_info"](student)
      #
      # # 后面python用一种更优雅的方式,把这些串到一起。
      # =====================================

       

 

 8.类和对象的关系是什么?

  • 学生A,小明;学生B,小红;学生C,小华......这些是对象,具体的人。
  • 他们的有共同的特点,都是学生,所以把他们归类成 [ 学生类 ] 
  • 总结:

    • 对象是具体的人或物,类是抽象人或物的集合。

 9.把对象转换为类

 

 10.探究类里面的东西

 

 

 

 

 

 11.定义类,调用类发生的事情。

  • 定义类发生的事:

    • 1.立刻运行类体代码
    • 2.将运行过程中产生的名字都丢到类的名称空间中
  • 调用类发生的事:

    • 1.创造一个对象的字典,用来存放对象独有的数据
    • 2.将对象与类建立好关联

 

12.类的初始化函数推演-1

  • 简化11行-17行
  •  

     

 

13.类的初始化函数推演-2

  • 1.把函数init放进类里面,建立关联

  • 2.让init自动调用,使用双下划线__

  •  

     

14.类的初始化函数推演-3



15.类的属性查找

  • 对象的属性:先从对象自己的字典找,没有再去类的字典里找

  • 类的属性:从自己的字典找

  • 类的数据属性:共享给所有对象的

  • class Student:
        school = "北京大学"
        def __init__(self, x, y, z):  # 加了双下划线,就会自动调用
            self.name = x
            self.age = y
            self.gender = z
    
        def tell_info(student):  # 公共函数
            print(f"学生的名字是{student['name']},年龄是{student['age']},性别是{student['gender']}")
    
    obj1 = Student("tom",19,"female")
    
    # 对象,属性的查找属性:先从对象的字典里找,再从类的字典里找
    
    print(obj1.name)    # obj1.__dict__['name']
    print(obj1.school)
    print(obj1.tell_info)
    
    # 类的属性:从类自己的字典里找
    print(Student.school)   # 北京大学
    print(Student.__init__)     # <function Student.__init__ at 0x0000028E5CCC29D0>
    print(Student.tell_info)    # <function Student.tell_info at 0x0000028E5CCDC1F0>
    
    # 类的数据属性是直接共享给所有对象用的
    Student.school = "新的大学"
    print(Student.school,id(Student.school)) # 新的大学 2810465115760
    print(obj1.school,id(obj1.school))  # 新的大学 2810465115760
    View Code

     

 16.类的绑定方法 

  • 类中的函数,是为对象服务的。

    • 为了方便使用,python自动帮把调用者obj1本身当做第一个参数传入。
  • 类的可以直接调用自己的方法。(等同于普通函数)

  • obj1.fun()会报错?背后的原因就是类把对象obj1当做第一个参数传入。

  • class Student:
        school = "北京大学"
        def __init__(self, x, y, z):
            self.name = x
            self.age = y
            self.gender = z
    
        def tell_info(self):   # 变量名更改为self,下面也同步更改
            print(f"学生的名字是{self.name},年龄是{self.age},性别是{self.gender}")
    
        def fun():  # 类中的函数(方法)是给对象使用的。
            print("xxxx")
    
    obj1 = Student("tom",19,"female")
    obj2 = Student("liqi",16,"male")
    
    # 类中的函数:相当于普通函数,该怎么传参数就参数
    # 但其实类中的函数是给对象用
    # 对象来调用就是一个绑定方法,绑定方法的特点是会将调用当做第一个参数自动传入
    print(Student.tell_info)
    Student.tell_info(obj1)
    Student.tell_info(obj2)
    
    # 对象的方法: 绑定方法,自动把调用者当做第一个参数传入。
    print(obj1.tell_info)  # 这是绑定方法
    # 结果为 <bound method Student.tell_info of <__main__.Student object at 0x0000018C63BA8E20>>
    
    obj1.tell_info()    # 把调用者obj1传入==> obj1.tell_info(obj1)
    
    # 可以这样使用,但类中的函数,是给对象使用的
    Student.fun()
    obj1.fun()  # TypeError: fun() takes 0 positional arguments but 1 was given

     

 

 17.类中的术语:

  • 类中的字典,叫属性。

  • 类中的函数def ,叫方法。

 

 18.封装是什么?

  • 最简单来讲,封装是一种思想。把东西放到一起,方便使用。

  • 举例来说,就是把东西放到麻袋里,外面看就是一个麻袋,里面装有很多东西。
  • 在举例来书,书包也是一种封装,把书本,笔,电脑等封装到一个书包里。

 

 19.类的隐藏属性

  • 利用__country来隐藏属性

  • class People:
        # country = "China"
        __country = "China"
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    # print(People.country)
    
    # 隐藏后
    # print(People.country) # 访问不到
    # print(People.__country) # 也访问不到
    
    print(People.__dict__)  # 分析底层原理
    print(People._People__country)  # 可以访问到
    View Code

     

20.类的隐藏方法

  • 利用__func(self)来隐藏
  • class People:
        # country = "China"
        __country = "China"
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __func(self):
            print("xxx")
    
    # print(People.country)
    
    
    print(People.__dict__)  # 分析底层原理
    obj1 = People("LIQI",15)    # 建立个self对象给到下面
    People._People__func(obj1)  # 可以访问隐藏方法 xxx
    View Code

     

 21.类的隐藏init的属性

  • 利用self.__name = name来隐藏
  • class People:
        __country = "China"
    
        def __init__(self, name, age):
            self.__name = name
            self.__age = age
    
        def __func(self):
            print("xxx")
    
    
    # print(People.__dict__)  # 分析底层原理
    
    obj1 = People("tom", 20)  # 建立个self对象给到下面
    print(obj1.__dict__)    # 查看对象的字典
    # {'_People__name': 'tom', '_People__age': 20}
    
    print(obj1._People__age)    # 非要访问的话
    View Code

     

 22.类的__开头的属性特点:

  • 1.并没有真正的隐藏,只是变形

  • 2.该变形只在类的定义阶段,扫描语法的时候执行,此后__开头的属性,不会变形。

  • 3.该隐藏对外不对内

  • 代码-特点2
  • obj1 = People("tom", 20)
    print(obj1.__dict__)    # 变形
    obj1.__gender = "female"
    print(obj1.__dict__)    # 后赋值,不变形

     

  • 代码-特点3-对外不对内:
  • class People:
        __country = "China"
    
        def __init__(self, name, age):
            self.__name = name
            self.__age = age
    
        def __func(self):
            print("xxx")
    
        def tell_name(self):
            print(self.__name)
            
    obj1 = People("tutu",18)
    obj1.tell_name()
    View Code

     

     

23.类的隐藏属性,为什么要隐藏?

  • 类中的东西,要么是数据,要么是功能。
  • 为什么要隐藏属性(数据)?
  • 准确来说__开头的数据,不是隐藏起来,是保护起来。
    • 控制数据的访问形式。
    • 用函数的形式,保护数据的类型,增加逻辑判断等。
    • 比如:self.__name的修改

 

24.类的隐藏函数,为什么要隐藏?

  • 有些琐碎的功能,不希望别人调用。
  • 仅供内部使用的。
  • 专业一点:隔离复杂度。
  • 生活中,比如,开机只有一个键。
    • 开机背后,封装了很多复杂的功能。

 25.类是什么?

  • 类是对象的归纳,是盛放对象与对象之间的公共部分,解决冗余问题的。

26.类和类之间要是有冗余怎么办?

  • 这就引出了类的【继承】的概念。
  • 继承就是为解决类与类支间的冗余。

27.继承有缺点吗?

  • 有,继承是一种强耦合,彼此关联性强。
  • 跟面向对象的扩展性的思想相悖。
  • 所以要辩证的来看待。

 28.类与对象的区别?

  • 对象是盛放相关的数据和功能的容器。
  • 类是盛放对象相似的数据和功能的容器。

29.比如一个学生类有很多数据,如何确定哪些数据是要用的?

  • 根据场景来分析。
  • 比如,学生数据中可以有,学号,性别,班级,爱好,兴趣,吃喝拉撒等等。
  • 但在一个具体的场景,选课系统。那么学号,班级,就有关系。其他就信息就不重要,可以舍弃。
  • 实际公司中,具体的需求分析,是产品经理组织开会,一起讨论出来的。

 30.实例化是什么?

  • 调用类的过程。
  • (类是虚的,是抽象的,是概念的;实例是具体的事务,是小华,是小明,是实实在在的人,是实际的。)

 31.如何在类里面统计有多少对象调用这个类的功能?

  • 利用类调用时,自动触发__init__的功能来写。
  • class Student:
        n = 0
    
        def __init__(self, x, y, z):
            Student.n += 1  # 利用类定义自动调用函数,来统计有几个对象调用了
            self.name = x
            self.age = y
            self.gender = z
    
        def choose(self):
            pass
    
    
    obj1 = Student("liqi", 18, "male")
    # Student.n +=1
    obj2 = Student("liqi", 28, "male")
    # Student.n +=1
    obj3 = Student("liqi", 38, "male")
    # Student.n +=1
    
    print(obj1.n)  # 3
    print(obj2.n)  # 3
    print(obj3.n)  # 3
    View Code

     

 

 

 

 

 

 

 

 

 

 

  • 参考资料:

 

posted @ 2023-01-31 23:40  o蹲蹲o  阅读(28)  评论(0编辑  收藏  举报