第九章、面向对象

第九章、面向对象

一、类的定义

  1. 格式:

    • # classnam类名
      class classname(object):
          """
          代码段
          """
          pass
      
  2. 调用方式:实例化

    • class Student():
          name = ""
          age = 0
          def print_file():
              pass
      # 实例化
      student = Student()
      # 调用类下面的方法
      student.print_file()
      # 运行会报错
      # 解决方法
      在方法中间写入self
      class Student():
          name = ""
          age = 0
          def print_file(self):
              print("name:"+name)
              print("age:"+str(age))
      student = Student()
      student.print_file()
      # 运行结果
      还是报错
      继续修改
      class Student():
          name = ""
          age = 0
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      student = Student()
      student.print_file()
      # 运行结果
      name:
      age:0
      
    • 类的最基本的作用就是封装代码

    • 类中的方法在书写时参数一定要加self

二、类与对象

  1. 在别的模块中引用类

    • from c1 import Student
      student = Student()
      student.print_file()
      # 结果:
      name:
      age:0
      
  2. 方法和函数的区别

    • 没有一个绝对的区别
  3. 定义在类中的变量不能叫变量,应该是数据成员,定义在类外面的数据才叫变量

  4. 类:

    1. 什么是类?
      • 类就是将数据和对这些数据的操作封装在了一起
      • 类是一个事物的抽象,并不是具体的
      • 数据成员刻画特征
      • 方法刻画行为,行为需要找对主体
      • 类就像一个模板一样,通过类可以产生很多个对象
  5. 对象:

    1. 什么是对象
      • 对象则是表示一个具体的事物,就是将类实例化
      • 当类被实例化之后就会变成实例对象
      • 只有给实例化后的类传入特征值,对象才能有对应特征
  6. 实例化:

    • class Student():
          name = ""
          age = 0
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student()
      student2 = Student()
      student3 = Student()
      # 创建3个不同的实例化对象,特征是相同的,但是实际上又是独立开的不同的对象
      

三、构造函数

  1. 如果要在类中传入特征值,需要定义一个特殊的函数__init__()

  2. class Student():
        name = ""
        age = 0
        def __init__(self):
            # 构造函数
            print("student")
            pass
        def print_file(self):
            print("name:"+self.name)
            print("age:"+str(self.age))
    
    student1 = Student()
    student1.__init__()
    # 结果:
    student
    student # 出现了两次打印
    
  3. 出现两次的原因是因为当我们实例化类的话,构造函数会被自动调用,也可以主动调用构造函数

  4. 构造函数返回值是None,不能返回别的值

  5. 构造函数的作用

    1. 可以让模板生成不同的对象

    2. 在构造函数中创建了形参后,就必须在实例化类中写入实参,不写的话会报错

      class Student():
          # name = ""
          # age = 0
          def __init__(self,name,age):
              # 构造函数
              print("student")
              pass
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student()
      student1.__init__()
      # 运行结果:
      报错
      class Student():
          # name = ""
          # age = 0
          def __init__(self,name,age):
              # 构造函数
              print("student")
              pass
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      student1 = Student('刘小刚', 2)
      student1.print_file()
      # 运行结果:
      student
      空 # 并没有修改成功
      
      class Student():
          name = ""
          age = 0
          def __init__(self,name,age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
              print("student")
              pass
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student('刘小刚', 2)
      student1.print_file()
      # 运行结果:
      student
      name:刘小刚
      age:2
      

四、类变量1和实例变量2

  1. 类变量:是定义在类中的变量

    • class Student():
          # 类变量
          name = ""
          age = 0
          def __init__(self,name,age):
              # 构造函数
              # 初始化对象的特征
              # 实例变量
              self.name = name
              self.age = age
              print("student")
      
    • 类变量的意义:类变量和特征变量是无关的,也就是和成员属性是无关的

  2. 实例变量:是定义在__init__()中,实例变量的定义方式是self.变量名

    • class Student():
          # 类变量
          name = ""
          age = 0
          def __init__(self,name,age):
              # 实例变量
              self.name = name
              self.age = age
              print("student")
      
  3. 实例变量和类变量的区别

    • class Student():
          name = "qiyue"
          age = 0
          def __init__(self,name,age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
      
      student1 = Student('刘小刚', 2)
      print(student1.name)
      print(Student.name)
      # 结果:
      刘小刚
      qiyue
      
    • 对象的.name和实例对象的.name是不同的

  4. __dict__3

    • class Student():
          name = "qiyue"
          age = 0
          def __init__(self,name,age):
              # 构造函数
              # 初始化对象的特征
              name = name
              age = age
      
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student('刘小刚', 2)
      print(student1.name)
      # 结果:
      qiyue
      
    • 为何没有修改该变量

    • class Student():
          name = "qiyue"
          age = 0
          def __init__(self,name,age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              age = age
      
          def print_file(self):
              print("name:"+self.name)
              print("age:"+str(self.age))
      
      student1 = Student('刘小刚', 2)
      
      print(student1.__dict__)
      # 结果
      只有一个实例变量,{'name': '刘小刚'}
      
    • 为什么实例变量不存在,还能打印出qiyue

      • 这和变量的寻找机制有关,当在特征变量中找不到值的时候,他就会到类中寻找,若在类中也找不到,那么就会向上(父类)中继续寻找
  5. self

    • 特性:如果要在类中定义一个实例方法,那么第一个参数需要写self,而在我们调用这个方法发时候是不需要传入这个参数的,self是默认传入的
    • self可以不叫self,可以写this或别的,但是python建议我们用self,显胜与隐
    • self的意义:调用这个方法的实例对象,换句话说就是self代表的是调用的对象,而不是类
  6. 实例方法:

    • 是和对象相关联的方法

    • 实例方法中访问类变量

    • 在实例方法中无法访问类变量。

      • class Student():
            name1 = "qiyue"
            age1 = 0
            def __init__(self, name, age):
                # 构造函数
                # 初始化对象的特征
                self.name = name
                self.age = age
                print(name1)
                print(age1)
                
        student1 = Student('刘小刚', 2)
        # 结果
        报错
        
    • 通过类名直接调用类变量、或者通过self.__class__.类变量名

      • class Student():
            name1 = "qiyue"
            age1 = 0
            def __init__(self, name, age):
                # 构造函数
                # 初始化对象的特征
                self.name = name
                self.age = age
                # print(Student.name1)
                print(self.__class__.name1)
                # print(Student.age1)
                print(self.__class__.age1)
        
        student1 = Student('刘小刚', 2)
        # 结果
        qiyue
        0
        

五、类方法

  1. 为什么会有类方法

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
              Student.sum1 += 1
      student1 = Student('刘小刚', 2)
      student2 = Student('刚小刘', 2)
      student3 = Student('小刘刚', 2)
      print(Student.sum1)
      # 结果:
      3
      
    • 每创建一个对象,类变量都会自动加一

  2. 类方法定义:

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 实例方法
              print("name:"+self.name)
              print("age:"+str(self.age))
      
          @classmethod
          def plus_sum(cls):
              # 类方法
              pass
      
    • @classmethod@是装饰器的定义

    • cls:是默认参数,可以更改,代表的是类

    • 用来操作和类相关的变量

      • class Student():
            name1 = "qiyue"
            age1 = 0
            sum1 = 0
            def __init__(self, name, age):
                # 构造函数
                # 初始化对象的特征
                self.name = name
                self.age = age
                Student.sum1 += 1
        
            def print_file(self):
                # 实例方法
                print("name:"+self.name)
                print("age:"+str(self.age))
        
            @classmethod
            def plus_sum(cls):
                # 类方法
                cls.sum1 += 1
                print(cls.sum1)
        
        student1 = Student('刘小刚', 2)
        Student.plus_sum()
        student2 = Student('刚小刘', 2)
        Student.plus_sum()
        student3 = Student('小刘刚', 2)
        Student.plus_sum()
        print(Student.sum1)
        # 结果:
        2 4 6 6
        
      • 类方法时可以用对象直接调用的

      • 可以看出类并没有实例化,可以通过类直接调用类函数。
        当然类方法,实例也可以调用,但是并没有什么用,违反了初衷:类方法就是专门供类使用

六、静态方法

  1. 静态方法的定义

    • 没有强制传入参数、就是一个普普通通的方法

    • class Student():
          @staticmethod
          def add(x,y):
              # 静态方法
              print("This is a static method")
      
      student1 = Student('刘小刚', 2)
      # 结果
    • 对象和类都可以调用这个方法

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 实例方法
              print("name:"+self.name)
              print("age:"+str(self.age))
      
          @classmethod
          def plus_sum(cls):
              # 类方法
              cls.sum1 += 1
              print(cls.sum1)
              pass
      
          @staticmethod
          def add(x,y):
              print("This is a static method")
      
      student1 = Student('刘小刚', 2)
      student1.add(1,1)
      Student.add(1,3)
      # 结果:
      This is a static method
      This is a static method
      
    • 静态方法内部也可以调用类变量

    • 静态方法和类关联非常弱,可以用在和类没有太大关系的时候用

七、成员4可见性:公开5和私有6

  1. 类的内外之分

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 实例方法
              print("name:"+self.name)
              print("age:"+str(self.age))
              self.do_homework()
              
          def do_homework(slef):
              # 实例方法
              pass
      
      student1 = Student('刘小刚', 2)
      
  2. 使用实例方法对实例变量的值进行修改

    • 通过对象操作实例变量是不安全的,可以通过方法来操作实例变量会更加安全,因为可以对实例变量进行限制

    • class Student():
          name1 = "qiyue"
          age1 = 0
          sum1 = 0
          def __init__(self, name, age):
              # 构造函数
              # 初始化对象的特征
              self.name = name
              self.age = age
              Student.sum1 += 1
      
          def print_file(self):
              # 实例方法
              print("name:"+self.name)
              print("age:"+str(self.age))
              self.do_homework()
      
          def marking(self,score):
              # 实例方法
              if score < 0:
                  return "不能够打负分"
              self.score = score
              print(self.name + "同学本次成绩为:"+str(self.score))
      
      student1 = Student('刘小刚', 2)
      student1.marking(59)
      # 结果:
      刘小刚同学本次成绩为:59
      result = student1.marking(-1)
      print(result)
      # 结果:
      不能够打负分
      
  3. 变量私有化:

    • __:双下划线对变量和方法进行私有化

    • 构造函数是特有函数,所以可以访问

    • class Student():
          # 类变量
          sum1 = 0
          # 成员属性
          def __init__(self):
              self.__name = "刘小刚"
              self.__age = "10"
          def __marking(self):
              # 私有方法
              print("刘小刚很厉害,张小方很菜")
      
      student1 = Student()
      student1.__marking()
      # 运行结果:
      AttributeError: 'Student' object has no attribute '__marking'
      私有方法无法调用
      
    • # 为什么私有成员属性不光可以访问,而且还能改变值
      class Student():
          # 类变量
          sum1 = 0
          # 成员属性
          def __init__(self):
              self.__name = "刘小刚"
              self.__age = "10"
          def __marking(self):
              print("刘小刚很厉害,张小方很菜")
              pass
      student1 = Student()
      # student1.__marking()
      student1.__name = "张小方"
      print(student1.__name)
      # 结果:
      张小方
      
    • 注意:之所以可以访问是因为,.__变量名是新建成员变量,原来的变量是无法进行访问的,因为名字已经被修改了,不能通过动态方式创建私有变量

    • class Student():
          # 类变量
          sum1 = 0
          # 成员属性
          def __init__(self):
              self.__name = "刘小刚"
              self.__age = "10"
          def __marking(self):
              print("刘小刚很厉害,张小方很菜")
              pass
      
      student1 = Student()
      student1.__name = "张小方"
      print(student1.__dict__)
      # 结果:
      {'_Student__name': '刘小刚', '_Student__age': '10', '__name': '张小方'}
      
    • class Student():
          # 类变量
          sum1 = 0
          # 成员属性
          def __init__(self):
              self.__name = "刘小刚"
              self.__age = "10"
          def __marking(self):
              print("刘小刚很厉害,张小方很菜")
              pass
      student1 = Student()
      print(student1._Student__age)
      # 结果:
      10
      

八、继承

  1. 一个代码块中最好只定义一个类

  2. # c5.py
    # 父类
    class people():
        pass
    
    # c6.py
    from c5 import people
    # 继承
    class Student(people):
        # 类变量
        sum1 = 0
        # 成员属性
        def __init__(self):
            self.__name = "刘小刚"
            self.__age = "10"
    
        def __marking(self):
            print("刘小刚很厉害,张小方很菜")
            pass
    student1 = Student()
    
  3. 创建对象调用

    • # c5.py
      class Human():
          # 类变量
          sum1 = 0
          # 成员属性
          def __init__(self, name, age):
              self.name = name
              self.age = age
          # 类方法
          def get_name(self):
              print(self.name)
      # c6.py
      from c5 import Human
      # 类、对象
      class Student(Human):
          # 类变量
          # 成员属性
          pass
      student1 = Student("刘小刚","10")
      print(student1.sum1)
      print(student1.name)
      print(student1.age)
      # 运行结果:
      0
      刘小刚
      10   # 子类继承父类的变量
      
  4. 一个父类有多个子类,子类的下面也能有子子类,深度不限(单继承)

  5. from c5 import Human
    # 类、对象
    class Student(Human):
        # 类变量
    
        # 成员属性
        def __init__(self,school,name,age):
            self.school = school
            Human.__init__(self,name,age)
    
    student1 = Student("七彩幼儿园","刘小刚","10")
    print(student1.school)
    print(student1.name)
    print(student1.age)
    # 运行结果:
    七彩幼儿园
    刘小刚
    10
    
  6. 为什么需要在__init__()中传入self:因为在实例化对象的时候,python自动帮忙将self传入进去,而是用类名.实例方法 的这种操作就相当于是在调用实例方法,就是当成函数来调用,你们就要传入参数

  7. from c5 import Human
    # 类、对象
    class Student(Human):
        # 类变量
    
        # 成员属性
        def __init__(self,school,name,age):
            self.school = school
            Human.__init__(self,name,age)
    
        def do_homework(self):
            print("do_homework")
    
    student1 = Student("七彩幼儿园","刘小刚","10")
    # 等价
    student1.do_homework()
    Student.do_homework(student1)
    # 结果:
    do_homework
    do_homework
    
  8. 正要调用的缺点:当父类方法多次被调用时,需要多次更改父类名字

  9. 第二种调用父类方法的方式super,相当于代表父类这个关键字

    • from c5 import Human
      # 类、对象
      class Student(Human):
          # 类变量
      
          # 成员属性
          def __init__(self,school,name,age):
              self.school = school
              # Human.__init__(self,name,age)
              super(Student,self).__init__(name,age)
      
          def do_homework(self):
              print("do_homework")
      
      student1 = Student("七彩幼儿园","刘小刚","10")
      student1.do_homework()
      # 结果:
      do_homework
      
    • super(父类名,self):也可以调用父类中重名的方法

    • from c5 import Human
      # 类、对象
      class Student(Human):
          # 类变量
      
          # 成员属性
          def __init__(self,school,name,age):
              self.school = school
              # Human.__init__(self,name,age)
              super(Student,self).__init__(name,age)
      
          def do_homework(self):
              super(Student,self).do_homework()
              print("do_homework")
      
      student1 = Student("七彩幼儿园","刘小刚","10")
      student1.do_homework()
      # 结果:
      do_english_homework
      do_homework
      
  • super(父类名,self):也可以调用父类中重名的方法

  • from c5 import Human
    # 类、对象
    class Student(Human):
        # 类变量
    
        # 成员属性
        def __init__(self,school,name,age):
            self.school = school
            # Human.__init__(self,name,age)
            super(Student,self).__init__(name,age)
    
        def do_homework(self):
            super(Student,self).do_homework()
            print("do_homework")
    
    student1 = Student("七彩幼儿园","刘小刚","10")
    student1.do_homework()
    # 结果:
    do_english_homework
    do_homework
    

  1. 类变量是和类相关联的变量 ↩︎

  2. 实例变量是和对象相关联的变量 ↩︎

  3. 查看实例变量,和类变量,用键值对的方式返回 ↩︎

  4. 成员是指变量和方法 ↩︎

  5. 公开的那么就可以任意调用 ↩︎

  6. 私有的,则不行 ↩︎

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页