• 疫情环境下的网络学习笔记 python 4.7


    4.7

    今日正课

    面向对象编程

    • 一种编程思想,与面向对象一样相当于武功不同的流派,没有高低之分,各自有应用场景
    • 面向过程,核心是“过程”,过程是流水线,是用来解决问题的步骤,核心思想是将程序流程化
    • 面向对象,核心是对象

    对象

    • 对象是“容器”,是用来盛数据和功能的,可以看作数据和功能的集合体
    • 对象的奥义就是将程序“整合”

    举例

    需求1:选课系统

    # 程序中应该有学生的数据,课程的信息,以及操作的功能
    # 学生信息
    stu_name = 'deimos'
    stu_age = 18
    stu_sex = 'male'
    
    # 学生功能,例:打印学生的信息
    def show_info():
        print('名字:%s 年龄:%s 性别:%s'%(stu_name,stu_age,stu_sex))
        
    # 学生功能,改学生信息
    def set_info():
        global stu_name,stu_sex,stu_age
        stu_name =x
        stu_sex = y
        stu_age = z
        
    # 课程数据
    course_name = 'python'
    course_period = '6mons'
    course_score = 10
    
    # 课程的功能,例:打印课程信息
    def show_course():
        print(course_name,course_period,course_score)
        
    

    像这样,数据和功能分开,我们发现有一些功能只会操作一部分数据,如课程功能只操作课程的数据,但是所有的数据和功能都放在一起,混乱。所以希望把每种功能和数据分别进行整合

    # 学生的容器 = 学生的数据 + 学生的功能
    # 课程的容器 = 课程的数据 + 课程的功能
    

    整合后,不同类型的功能和数据分割开,解开耦合

    需求2:化妆

    • 要化妆,需要准备好原材料和工具

      • 原材料:眼影,粉底
      • 工具:眼线笔,粉扑
    • 类似地,原材料和工具对应编程中的数据和功能。如果不同作用的工具和原材料放在一起,很乱,比如椒盐和眼影放在一起,锅铲和眼线笔放在一起。所以把做菜的工具和材料,与化妆的材料和工具,分别整合后分开装到容器里,要化妆的时候使用化妆的容器,做菜的时候使用做菜的容器

    • 我们之前学的模块,把不同用处的功能和数据分开成多个文件,其实就是用面向对象的思想编程,模块就是一个对象。但是用文件整合功能单位比较大,希望有一种别的方式

    • 字典中可以放数据,函数名,一个字典当作一个容器,里面放相关功能和数据,也是一种方法,但是字典里的函数还是要在字典之外定义,不能把函数体代码放进字典,还是不够精简,达不到真正整合的需求

      在使用方法的时候,直接把字典传给这个方法,让方法去字典中找需要的数据和功能

    python中有语法允许我们将数据和功能很好地整合到一起

    类介绍

    • 两个具有相同属性的对象,其中有不一样的数据,也有一样的数据。使用多个具有相同属性的对象,不需要存多个同样的数据:使用“类”
    • 类也是容器,该容器用来存放同类对象共有的数据和功能
    • 必须要事先定义类,然后再调用类产生对象(调用类拿到的返回值就是对象)。产生对象的类与对象之间存在关联,这种关联指的是:对象可以访问到类中共有的数据与功能,所以类中的内容仍然是属于对象的,类只不过是一种节省空间、减少代码冗余的机制,面向对象编程最终的核心仍然是去使用对象

    面向对象的语法

    先定义类,再调用类产生对象

    类语法

    定义类

    • 定义方式:class 类名:

    • 类最常用的是定义数据和功能,但其实可以包含任何其他代码

    • 类体代码在定义阶段就会运行,会产生类的名称空间,名称空间中放类中的各种名字

      # 命名类,使用驼峰体
      class Student:
          # 变量的定义
          stu_school = 'boy'
          # 功能的定义,传入一个对象,可以使用对象中的数据,对象可以是外部传入的
          def show_info(stu_obj):
              pass
          print('=====')
      
    • 使用 类名.__dict__ 可以以字典形式查看类中的所有名字

      通过类名.__dict__[名字] 操作字典的方式得到类字典中的名字和功能

    • python提供的语法,使用点 . 去访问类

      # 访问数据属性
      print(Sudent.school_name)
      # 访问函数属性
      print(Sudent.show_info)
      

    调用类

    调用类产生对象,将类实例化,拿到的返回值就是程序中的对象

    stu1_obj = Student()
    print(stu_obj.__dict__)
    # {}
    
    • 调用类不是执行类体代码,而是制造一个关联,此时对象中只有类中公有的数据和功能,没有独立的数据和功能,使用 __dict__ 看到的是空字典

    • 可以操作字典或使用点,为对象添加独有的功能和数据,添加后__dict__ 看到的是独有的内容

      class Students:
          school = 'new east'
          def cook(obj):
              print(f'My name is {obj.name}, my schol is {Students.school}')
      
      deimos = Students()
      deimos.name = 'deimos'
      print(deimos.__dict__)
      
      #{'name': 'deimos'}
      

    出现问题

    创建多个对象,多个对象需要添加多种同类的数据,比如每个学生对象,添加他们的年龄和名字,名字各不相同,但是纪录名字的变量名都是 student_name,student_age,为每个学生的每个名字和年龄都操作字典麻烦,需要改进

    改进一:使用函数初始化

    sut1_obj = Student()
    sut2_obj = Student()
    # 创建空对象
    def init(obj1,x,y,z):
        # 为空对象传入独有的属性
    	obj.stu_name = x
    	obj.stu_age = y
    	obj.stu_sex = z
        
    init(stu1_obj,'deimos',21,'male')
    init(stu2_obj,'aaa',21,'male')
    

    改进二:调用类产生对象的时候自动调用init产生独有属性的功能,把init放到类里面去,前后加上下划线

    • 只要在类中定义__init__()方法,python会在调用类的时候自动触发执行
    • 其中__init__ 会自动将调用类时产生的空对象作为第一个参数传进来,于是我们只需要传init中的其他参数

    于是,对于改进一,把__init__西写在类中,调用的时候传入init需要的其他参数

    class Students:
        school = 'New east'
        def __init__(obj,name,age):
            obj.name = name
            obj.age = age
        def cook(obj):
            print(f'My name is {obj.name}, my schol is {Students.school}, my age is {obj.age}')
    
    deimos = Students('deimos',18)
    # 在生成对象的时候就传入独有的参数
    deimos.cook()
    aaa = Students('aaa',20)
    aaa.cook()
    
    # My name is deimos, my schol is New east, my age is 18
    # My name is aaa, my schol is New east, my age is 20
    

    调用类的过程

    调用类的过程又称为实例化,发生了三件事

    1. 先产生一个空对象
    2. python会自动调用类中的 __init__ 方法,将空对象以及调用类时括号内传入的参数一并传给 __init__
    3. 返回初始化完的对象

    **总结__init__ 方法 **

    1. 会在调用类时自动触发执行,用来为对象初始化自己独有的数据
    2. init 内应该存放的是为对象初始化属性的功能,但是也可以放其他任意代码,例如想要在调用类的时候就立刻执行的代码
    3. init 默认返回None,也必须返回none

    属性查找问题

    查找对象中的数据,先从对象本身找,找不到则去类中找。查找类中的数据,访问到的是变量值,查找函数,找到的是函数的内存地址

    数据属性

    其实类中的东西都是给对象用的,同一类下共享的数据属性,在不同对象下访问的地址都一样

    • 类中本身的值一变,所有都对象的这个值都一起变
    • 本身不是类的值,而是通过init传进的独有的值,通过一个对象改变,则只能改变当前对象的

    例:计算实例化的次数

    # 每次实例化,都运行了一次__init__
    class atudent:
        count = 0
        def __init__(obj):
            atudent.count += 1
        # 改变Student的值,而不是obj的值
    
    deimos = atudent()
    print(deimos.count)
    

    函数属性

    类的函数属性是给对象用的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法,内存地址各不相同

    Student.show_info(stu1_obj)
    # 可以这样写,相当于使用一个普通函数,stu1作为参数传入,相当于普通函数
    # <function ...>
    stu1_obj.show_info()
    # 使用student1对象所在类下的公共方法,会被python识别为绑定方法,与普通函数不一样
    # <bound ...>
    

    绑定方法的特殊之处在于,谁来绑定方法就会将谁作为第一个参数自动传入。所以在类中定义的函数,一定要有一个参数 obj,用来接收绑定时候传进来的对象。如果定义的时候没有这个参数,相当于有实参没形参,会报错

    在类里面定义函数,一定要有一个参数,约定设为self,用于接收自动传入的对象

    class Student:
    	def show_info(self):
    		pass
    

    之前在学点方法的时候,遇到self,当它不存在,因为self是自动传进来的参数,被谁点绑定就是作用于谁,如list.append(item),相当于list.append(self,item)

    总结

    对于扩展性高的部分,可以使用面向对象,对于其他普通部分不一定要使用类对象

  • 相关阅读:
    mysql 允许远程登陆
    jade报错:unexpected token
    quartz定时任务
    Java调用脚本
    CentOS安装、卸载jdk
    CentOS系统没有javac命令
    IDEA Error:java: 未结束的字符串文字
    面试连环炮系列(三):synchronized怎么用的
    面试连环炮系列(二):你们的项目Redis做了集群部署吗
    面试连环炮系列(一):如何保证Redis高可用和高并发
  • 原文地址:https://www.cnblogs.com/telecasterfanclub/p/12654911.html
Copyright © 2020-2023  润新知