面向对象编程(oop)

类和面向对象(oop)

概述

  • oop思想
    任意一个任务,首先想到的是任务的构成和实现过程。html

  • 类和对象的概念python

    • 类:抽象名词,表明一个集合,表明一类事物。
    • 对象:具象的事物,单个个体。
  • 类的内容设计模式

    • 属性(变量):代表事物特征
    • 方法(函数):代表事物功能
  • 类的命名函数

    • 大驼峰比较规范。
    • 必须用class关键字。
    • 由属性和方法组成,其余不准出现。
    • 成员属性定义可直接用变量赋值,若是没有值需使用None。
  • 访问类和对象的成员oop

    # 对象成员检查
    obj.__dict__
    # 类成员检查
    class_name.__dict__
  • 实例设计

    # 定义一个简单的类
     class StudentPython():
     name = None
     age = 18
     def Studentplay(self):
         print("learning python")
    
     # David为对象,此时实例化类
     David = StudentPython()
     print(David.name)
     print(David.age)
     David.Studentplay()

类和对象的成员分析

  • 类和对象均可以储存成员,成员能够归类全部也能够归对象全部。code

  • 建立对象时,类中的成员不会放入对象中,而是获得一个空对象。orm

  • 经过对象对类中成员从新赋值或者经过对象添加成员时,对应成员会保存在对象中,而不会修改类成员。htm

  • 实例对象

    class Teacher():
        name = "aaa"
        age = 28
        def TeacherSay(self):
            self.name = "Mary"
            self.age = 20
            print("My name is {0}".format(self.name))
            print("My age is {0}".format(self.age))
      
    t = Teacher()
    print(t.name)  
    print(t.age)
    t.TeacherSay()
    
    '''
    aaa
    28
    My name is Mary
    My age is 20
    '''

关于self

  • self在对象的方法中表示当前对象自己,若是经过对象调用方法,那么该对象会自动传入到当前方法的第一个参数中。

  • self并非关键字,理论上能够用任何一个普通变量名代替。

  • 方法中有self形参的称为非绑定类的方法,能够经过对象访问,没有self的称为绑定类方法,只能经过类访问。

  • 实例

    class Teacher():
        name = "aaa"
        age = 28
        def TeacherSay(self):
            self.name = "Mary"
            self.age = 20
            print("My name is {0}".format(self.name))
            print("My age is {0}".format(self.age))
        def TeacherSayAgain():
            print(__class__.name)
            print(__class__.age)
            print("learning python")
    
    t = Teacher()
    t.TeacherSay()
    # 调用绑定类方法经过类访问
    Teacher.TeacherSayAgain()
    
    '''
    My name is Mary
    My age is 20
    aaa
    28
    learning python
    '''

面向对象的三大特性

封装,继承,多态

  • 封装
    • 三个级别:公开(public),受保护(protected),私有(private)。

    • 判别对象的位置:对象内部,对象外部,子类中。

    • 私有:私有成员是最高级别的封装,只能在当前类或对象中访问,外部不能访问。python的私有不是真私有,是一种为name mangling的更名策略。

      class Person():
          # name为共有成员
          name = "David"
          #__age为私有成员
          __age = 18
    • 受保护:将对象成员进行必定级别的封装,在父类和子类中能够访问,外部不能访问。

    • 公开:对对象成员没有任何操做,任何地方均可以访问。

  • 继承
    • 继承就是一个类能够得到另一个类中的成员属性和方法。

    • 被继承的为父类(基类或超类),用于继承的类为子类(派生类)。

    • 全部的类都继承自object类,即全部的类都是object类的子类。

    • 子类继承父类后并无将父类成员彻底赋值到子类,而是经过引用关系访问调用。

    • 子类一旦继承父类,可使用父类中除私有成员外的全部成员属性和方法,子类还能够定义独有的成员属性和方法。

    • 子类中定义的成员若是和父类成员相同,则优先使用子类成员。

    • 若是想在子类中扩充父类方法,能够在定义新方法时访问父类成员来进行代码重用,能够父类名.父类方法也能够super().父类方法的格式调用。
      super不是关键字,而是一个类。super的做用是获取MRO(MethodResolutionOrder)列表中的第一个类

      class Person():
          name = "None"
          __age = 18
          _score = 0
          def Study(self):
              print("learning python")
      
      class Student(Person):
          def HaveTest(self):
              print("have to take exam")
          # 扩充父类函数,方法一二
          def Study(self):
              Person.Study(self)# 注意这里有self
              self.HaveTest()
              '''
              super().Study()# 注意这里没有self
              # super(Student, self).Study()也能够
              self.HaveTest()
              '''    
                             
      David = Student()
      print(David.name)
      David.Study()
      
      '''
      None
      learning python
      have to take exam
      '''
    • 继承中的查找顺序:子类优先查找本身的变量,没有则查找父类变量;
      子类中若是构造函数没有定义,则按照MRO顺序查找调用父类的构造函数,子类有定义则不继续向上查找。
      构造函数:每次实例化第一个被自动调用的函数

    • 单继承和多继承:单继承每一个类只能继承一个类,多继承每一个类能继承多个类;单继承逻辑清晰语法简单但功能不能受限,多继承扩展方便但关系混乱且会出现菱形继承(钻石继承)问题。

    • MRO:是在多继承中用于保存继承顺序的一个列表;
      MRO计算原则:子类永远在父类前;若是多个父类则根据括号内类的书写顺序存放;若是多个类继承了同一个父类,孙子类中只会选取括号内第一个父类的父类。

  • 多态
    • 多态就是同一个对象在不一样状况下有不一样状态出现。

    • Mixin设计模式:主要采用多继承方式对类功能进行扩展。首先必须表示某一单一功能,若是有多个功能则写多个Mixin,当子类没有继承某一Mixin类也能照常工做。

      class Person():
          def __init__(self, name, age):
              self.name = name
              self.age = age
          def Play(self):
              print("have fun")
          def Sleep(self):
              print("sleeping...")
      # 建立一个Mixin
      class TeacherMixin():
          def Work(self):
              print("teaching somebody")
      
      class StudentMixin():
          def Study(self):
              print("learning python")
      
      class Student(Person, StudentMixin):
          pass
      class Teacher(Person):
          def __init__(self):
              self.name = "Alex"
      
      David = Student("David", 18)
      print("my name is {0}, my age is {1}".format(David.name, David.age))
      David.Study()
      David.Play()
      print("*" * 20)
      Alex = Teacher()
      print("my name is {0}".format(Alex.name))
      Alex.Sleep()
      
      '''
      my name is David, my age is 18
      learning python
      have fun
      ********************
      my name is Alex
      sleeping...
      '''

类相关函数

  • issubclass:检测一个类是不是另外一个类的子类。
  • isinstance:检测一个对象是不是一个类的实例。
  • hasattr:检测一个对象是否有成员xxx。
  • dir:获取对象的成员列表

类的成员描述符(属性)

  • 类的成员描述符是为了在类中对类的成员属性进行相关操做

  • 三种方式:使用类实现描述器;使用属性修饰符;使用property函数property(fget, fset, fdel, doc)

    class Person():
        '''
        property函数实例
        定义一个Person类,具备name,age属性,
        对于任意输入的name都但愿以大写字母保存
        '''
        def fget(self):
            # 返回操做后的属性
            return self._name
        def fset(self, name):
            # 传入须要操做的属性
            self._name = name.upper()
        def fdel(self):
            self._name = "NoName"
        name = property(fget, fset, fdel, "None")
        age = 18
      
    David = Person()
    David.name = "David"
    print("my name is {0}".format(David.name))
    '''
    my name is DAVID
    '''

类的内置属性

__dict__:以字典的方式显示类成员的组成
__doc__:获取类的文档信息
__name__:获取类的名称,若是在模块中使用则获取模块名称
__bases__:以元组方式显示类的全部父类

类的经常使用魔术方法

  • 魔术方法就是不须要认为调用,在特定的状况下自动触发的方法,统一特征是方法名被先后两个下划线包裹。
    __init__:构造函数
    __new__:对象实例化方法
    __call__:对象当函数时使用
    __str__:对象被看成字符串时使用
    __repr__:返回字符串
    __getattr__:访问一个不存在的属性时触发,此时不会报错
    __gt__:进行大于判断的时候触发
    __setattr__:对成员属性设置的时候触发

    # __setattr__示例
    class A():
        def __setattr__(self, name, value):
            print("设置属性{0}为{1}".format(name, value))
            '''
            这样会致使死循环
            self.name = value
            '''
            # 为了不这种状况,使用父类魔法函数
            super().__setattr__(name, value)
    a = A()
    a.age = 18

类和对象的三种方法

  • 实例方法:必需要建立实例对象才能调用,第一个参数必须是实例对象,该参数名通常约定为self,若是方法里面有初始化函数也必须对初始化函数进行传参。且只能由实例对象调用

  • 类方法:使用装饰器@classmethod,第一个参数必须是当前类对象,该参数名通常约定为cls,能够由实例对象和类对象调用。

  • 静态方法:使用装饰器@staticmethod,没有self和cls参数,能够由实例对象和类对象调用。
    参考博客Python 实例方法、类方法、静态方法的区别与做用

    class Person():
        def Work(self):
            print("have to work")
        @classmethod
        def Study(cls):
            print("have to study")
        @staticmethod
        def Sleep():
            print("sleeping...")
    # 实例方法
    p = Person()
    p.Work()
    #Person.Work()会报错
    # 类方法
    p.Study()
    Person.Study()
    # 静态方法
    p.Sleep()
    Person.Sleep()
相关文章
相关标签/搜索