zoukankan      html  css  js  c++  java
  • 八、类

    1. 类的分类

    类分为新式类经典类(基于Python2.x版本来说的,Python3.x版本中只有新式类。)

    1.1 经典类

    class Family:
        def __init__(self):
            pass
    

    1.2 新式类

    class Family(object):
        pass
    

    1.3 新式类和经典类的区别

    # 在Python2中,继承了object的就是新式类,默认的是经典类;
    # 在Python3中,都是新式类,默认继承了object(注意:为了程序又更好的向下兼容性,在Python3中定义类时,建议都写成class Family(object)这种格式,而不是class Family这种格式;
    # 新式类支持super语法,经典类不支持;
    # 在多继承中,新式类采用的是广度优先的查找方法,经典类采用的是深度优先的查找方法;
    # 新式类有mro方法,经典类没有mro方法。
    

    2. 类和对象

    对象面向对象编程的两个重要元素,在此之前,我们进行编码都是面向过程编程的。对象是类的实例化,一个类可以存在多个对象。

    class Family(object):
        pass
    
    obj = Family()
    
    # obj就是Family类的一个对象,上述obj = Family()的过程称为类的实例化。
    

    3. 类的成员

    3.1 类的公有成员

    class Family(object):
    
        # 公有属性
        family_name = '赵'
    
        # 公有绑定方法
        def income(self):
            print(self.family_name + '姓家庭的收支')
    
        # 公有普通方法
        def pay():
            print('每月固定支出')
    
    # Family类的实例化对象obj
    obj = Family()
    
    
    # 类调用公有属性
    print(Family.family_name)
    
    # 类不能调用公有绑定方法
    # Family.income()
    # TypeError: income() missing 1 required positional argument: 'self'
    
    # 类调用公有普通方法
    Family.pay()
    
    # 对象调用公有属性
    print(obj.family_name)
    
    # 对象调用公有绑定方法
    obj.income()
    
    # 对象不能调用公有普通方法
    # obj.pay()
    # TypeError: pay() takes 0 positional arguments but 1 was given
    
    
    # 输出结果
    赵
    每月固定支出
    赵
    赵姓家庭的收支
    

    3.2 类的私有成员

    # 类的私有成员是以两个连续的下划线'__'开头的字符串命名的,私有成员只能在该类内部使用,其实例化对象和派生类都不能使用。
    
    class Family(object):
    
        # 私有属性
        __family_money = 1000000
    
        # 私有方法
        def __save(self):
            print('家庭的储蓄:', self.__family_money)
    
    # 注意:通过_类名__私有成员名的方式可以强行调用类中的私有成员。
    

    4. 类中的方法

    4.1 类中的普通方法

    # 类中的普通方法是指:在类中定义的没有参数的函数,只有类自身可以调用,对象不能调用。
    
    class Family(object):
    
        def income():
            print('I am a normal method.')
    
    Family.income()
    obj = Family()
    obj.income()
    
    # 输出结果
    I am a normal method.
    Traceback (most recent call last):
      File "E:/python/pycharm/demo/advance/11类中的方法.py", line 12, in <module>
        obj.income()
    TypeError: income() takes 0 positional arguments but 1 was given
    

    4.2 类中的静态方法

    # 类中的静态方法是指:用staticmethod装饰器修饰的普通方法,类自身和对象都能调用。
    
    class Family(object):
    
        @staticmethod
        def income():
            print('I am a static method.')
    
    Family.income()
    obj = Family()
    obj.income()
    
    # 输出结果
    I am a static method.
    I am a static method.
    

    4.3 类中的绑定方法

    • 绑定到对象
    # 类中的绑定到对象的方法是指:在类中定义的第一个参数为self的函数,该方法只能对象调用,类自身不能调用。
    
    class Family(object):
    
        def income(self):
            print('I am a object method.')
    
    obj = Family()
    obj.income()
    Family.income()
    
    # 输出结果
    I am a object method.
    Traceback (most recent call last):
      File "E:/python/pycharm/demo/advance/11类中的方法.py", line 11, in <module>
        Family.income()
    TypeError: income() missing 1 required positional argument: 'self'
    
    • 绑定到类
    # 类中的绑定到类的方法是指:在类中定义的第一个参数为cls且用装饰器classmethod修饰的函数,该方法对象和类自身都能调用。
    
    class Family(object):
    
        @classmethod
        def income(cls):
            print('I am a class method.')
    
    obj = Family()
    obj.income()
    Family.income()
    
    # 输出结果
    I am a class method.
    I am a class method.
    
    • property装饰器
    # property装饰器的作用:将类中的方法变为属性,使得在调用时直接按照调用属性的方式调用该方法,并返回该方法的返回值。
    
    class Family(object):
    
        @property
        def income(self):
            print('I am property.')
            return 12345
    
    obj = Family()
    result = obj.income
    print(result)
    
    # 输出结果
    I am property.
    12345
    

    4.4 类中的魔法方法

    ​ Python中,以两个下划线__开头且以两个下划线__结尾的方法称为魔法方法

    • __new____init____call__

      # __new__魔法方法:用于创建空对象,称为“构造方法”;最先被调用,所有的类都继承了object类,该类中包含了__new__方法,需要重写时在自己的类中重新定义__new__即可。
      # __init__魔法方法:用来对象赋值,称为“初始化方法”,在__new__方法之后被调用。
      # __call__魔法方法:对象后面加括号,会自动调用__call__方法。
      
      class ClassA(object):
      
          def __init__(self):
              print('用于给对象赋值,初始化方法')
      
          def __new__(cls, *args, **kwargs):
              print('用于创建空对象,构造方法')
              return object.__new__(cls)
      
          def __call__(self, *args, **kwargs):
              print('执行call方法')
      
      obj1 = ClassA()
      # 对象后面加括号,会自动调用__call__方法
      obj1()
      
      # 输出结果
      用于创建空对象,构造方法
      用于给对象赋值,初始化方法
      执行call方法
      
    • __setitem____getitem__delitem__

      class ClassB(object):
      
          def __setitem__(self, key, value):
              # 'k1'传给key, 123传给value
              print(key, value)
      
          def __getitem__(self, item):
              # 'xxx'传给item
              print(item)
      
          def __delitem__(self, key):
              # 'ttt'传给key
              print(key)
      
      obj2 = ClassB()
      obj2['k1'] = 123  # 内部会自动调用 __setitem__方法
      obj2['xxx']  # 内部会自动调用 __getitem__方法
      del obj2['ttt']  # 内部会自动调用 __delitem__方法
      
      # 输出结果
      k1 123
      xxx
      ttt
      
    • __str__

      class ClassC(object):
      
          def __str__(self):
              '''
              只有在打印对象时,会自动调用此方法,并将其返回值在页面显示出来
              :return: 返回一个字符串
              '''
      
              return 'i can only return a string.'
      
      obj3 = ClassC()
      print(obj3, type(obj3))
      
      # 输出结果
      i can only return a string. <class '__main__.ClassC'>
      
    • __dict____doc____module__

      class ClassD(object):
          '''用来说明__dict__、__doc__和__module__的作用'''
      
          def __init__(self, name, age, email):
              self.name = name
              self.age = age
              self.email = email
      
      obj4 = ClassD('aaron', 19, '163.com')
      # 去对象中找到所有对象,并转化为字典
      result = obj4.__dict__
      print(result)
      # 得到当前类的说明文档
      result = obj4.__doc__
      print(result)
      # 得到当前操作的区域
      result = obj4.__module__
      print(result)
      
      # 输出结果
      {'name': 'aaron', 'age': 19, 'email': '163.com'}
      用来说明__dict__、__doc__和__module__的作用
      __main__
      
      • __add____sub____mul__
      class ClassE(object):
      
          def __add__(self, other):
              return '两个对象相加时我被调用了'
      
          def __sub__(self, other):
              return '两个对象相减时我被调用了'
      
          def __mul__(self, other):
              return '两个对象相乘时我被调用了'
      
      obj5 = ClassE()
      obj6 = ClassE()
      result = obj5 + obj6
      print(result)
      result = obj5 - obj6
      print(result)
      result = obj5 * obj6
      print(result)
      
      # 输出结果
      两个对象相加时我被调用了
      两个对象相减时我被调用了
      两个对象相乘时我被调用了
      

    5. 类的继承

    5.1 单继承

    # 单继承是指:只继承了一个基类(父类)的派生类(子类);基类的公有成员可以由派生类随意调用。
    
    class Father(object):
    
        def father(self):
            print('I am father.')
    
    # 继承了Father类
    class Son(Father):
    
        def son(self):
            print('I am son.')
    
    obj = Son()
    obj.son()
    obj.father()
    
    # 输出结果
    I am son.
    I am father.
    

    5.2 多继承

    # 多继承是指:继承了两个及以上的基类的派生类;基类的公有成员可以由派生类随意调用。
    
    class Father(object):
    
        def father(self):
            print('I am father.')
    
    class Mother(object):
    
        def mother(self):
            print('I am mother.')
    
    # 继承了Father类和Mother类
    class Son(Father, Mother):
    
        def son(self):
            print('I am son.')
    
    obj = Son()
    obj.son()
    obj.father()
    obj.mother()
    
    # 输出结果
    I am son.
    I am father.
    I am mother.
    
    • issubclass和isinstance
    # issubclass:判断指定类是否为某个类的派生类
    # isinstance:判断指定对象是否为某个类的实例化对象
    
    class Grandfather(object):
    
        def grandfather(self):
            print('I am grandfather.')
    
    class Father(Grandfather):
    
        def father(self):
            print('I am father.')
    
    class Aunt(object):
    
        def anut(self):
            print('I am aunt.')
    
    class Son(Father):
    
        def son(self):
            print('I am son.')
    
    # 判断指定类是否为某个类的派生类
    result = issubclass(Son, Father)
    print(result)
    result = issubclass(Son, Grandfather)
    print(result)
    result = issubclass(Son, Aunt)
    print(result)
    
    obj = Son()
    # 判断指定对象是否为某个类的实例话对象
    result = isinstance(obj, Son)
    print(result)
    result = isinstance(obj, Father)
    print(result)
    result = isinstance(obj, Grandfather)
    print(result)
    result = isinstance(obj, Aunt)
    print(result)
    
    # 输出结果
    True
    True
    False
    True
    True
    True
    False
    
    • super()调用父类方法
    # super是一个类;super()是一个对象,用于根据mro列表调用下一个类的绑定方法。
    # super的作用:派生类中出现基类中的同名绑定方法时,可以既调用派生类中的方法,又调用基类中的方法。
    
    class Grandfather(object):
    
        def money(self):
            print("grandfather")
    
    class Father(Grandfather):
    
        def money(self):
            print("father1")
            super().money()
            print("father2")
    
    class Mother(Grandfather):
    
        def money(self):
            print("mother1")
            super().money()
            print("mother2")
    
    class Son(Father, Mother):
    
        def money(self):
            print('son1')
            super().money()
            print('son2')
    
    # 获取使用mro列表
    find_list = Son.mro()
    print(find_list)
    
    obj = Son()
    obj.money()
    
    # 输出结果
    [<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class '__main__.Grandfather'>, <class 'object'>]
    son1
    father1
    mother1
    grandfather
    mother2
    father2
    son2
    
    # 注意:新式类才支持super和mro方法,mro列表是根据C3算法计算出来的顺序列表,用在多继承中super调用各个类中的同名方法时参照的顺序。
    
    • 深度优先和广度优先
    # 在多继承中,调用类中的同名方法时采用的查找方法分为深度优先和广度优先。
    # Python2.x:采用深度优先
    # Pyhton3.x:采用广度优先
    
    class Grandfather(object):
    
        def money(self):
            print("I am grandfather's money.")
    
    class Father(Grandfather):
    
        pass
    
    class Mother(Grandfather):
    
        def money(self):
            print("I am mother's money.")
    
    class Son(Father, Mother):
    
        pass
    
    obj = Son()
    obj.money()
    
    # 输出结果
    # Python2.x:I am grandfather's money.
    # Python3.x:I am mother's money.
    

    5.3 约束

    '''
    若在基类中有一个定义了一个方法如下所示:
    def sex(self):
        raise NotImplementedError()
    若存在派生类类继承了该基类,则,派生类中必须定义一个sex方法!
    '''
    
    class Father(object):
    
        def sex(self):
            raise NotImplementedError()
    
    class Son(Father):
    
        pass
    
    class Daughter(Father):
    
        def sex(self):
            print('I am a girl.')
    
    obj1 = Daughter()
    obj1.sex()
    obj2 = Son()
    obj2.sex()
    
    # 输出结果
    I am a girl.
    Traceback (most recent call last):
      File "E:/python/pycharm/demo/advance/13约束.py", line 22, in <module>
        obj2.sex()
      File "E:/python/pycharm/demo/advance/13约束.py", line 7, in sex
        raise NotImplementedError()
    NotImplementedError
    

    5.4 反射

    根据字符串的形式去某个对象中操作其成员。

    • getattr(对象, "字符串")

      # 根据字符串去指定对象中获取对应和字符串相同名称的成员。
      
      class Father(object):
      
          def __init__(self, money):
              self.money = money
      
          def house(self):
              print(self.money)
      
      obj = Father(12345)
      # 获取属性
      result = getattr(obj, 'money')
      print(result)
      # 获取方法
      result = getattr(obj, 'house')
      result()
      
      # 输出结果
      12345
      12345
      
    • hasattr(对象, "字符串")

      # 根据字符串判定指定对象中是否有对应和字符串相同名称的成员。
      
      class Father(object):
      
          def __init__(self, money):
              self.money = money
      
          def house(self):
              print(self.money)
      
      obj = Father(12345)
      result = hasattr(obj, 'money')
      print(result)
      result = hasattr(obj, 'house')
      print(result)
      result = hasattr(obj, 'car')
      print(result)
      
      # 输出结果
      True
      True
      False
      
    • setattr(对象, "变量名", "值")

      # 在指定对象中设置成员。 
      
      class Father(object):
      
          def __init__(self, money):
              self.money = money
      
          def house(self):
              print(self.money)
      
      obj = Father(12345)
      setattr(obj, 'family_name', 'Lions')
      print(obj.family_name)
      
      # 输出结果
      Lions
      
    • delattr(对象, "字符串")

      # 删除指定对象中对应和字符串相同名称的成员。 
      
      class Father(object):
      
          def __init__(self, money):
              self.money = money
      
          def house(self):
              print(self.money)
      
      obj = Father(12345)
      result = hasattr(obj, 'money')
      print('执行delattr之前', result)
      delattr(obj, 'money')
      result = hasattr(obj, 'money')
      print('执行delattr之后', result)
      
      # 输出结果
      执行delattr之前 True
      执行delattr之后 False
      

    5.5 单例模式

    无论实例化多少次,都用第一次创建的那个对象。

    • 格式
    class Singleton(object):
        __obj = None
    
        def __new__(cls, *args, **kwargs):
            if cls.__obj is None:
                cls.__obj = object.__new__(cls)
    
            return cls.__obj
    
    obj1 = Singleton()
    print(obj1)
    obj2 = Singleton()
    print(obj2)
    
    # 输出结果
    <__main__.Singleton object at 0x000001B7952E34E0>
    <__main__.Singleton object at 0x000001B7952E34E0>
    
    • 例子1
    class Singleton(object):
        __obj = None
    
        def __init__(self, name):
            print('This is Singleton.')
            self.name = name
    
        def __new__(cls, *args, **kwargs):
            if cls.__obj is None:
                cls.__obj = object.__new__(cls)
    
            return cls.__obj
    
    obj1 = Singleton('Aaron')
    obj2 = Singleton('Joe')
    print(obj1.name)
    print(obj2.name)
    
    # 输出结果
    This is Singleton.
    This is Singleton.
    Joe
    Joe
    
    # 注意: 上述例子并不是完全的单例模式, 因为每创建一个对象就会执行一次初始化__init__
    
    • 例子2
    # 此例在于解决例子1中的问题: 每创建一个对象就会执行一次初始化__init__
    # 完全的单例模式应该不论创建多少个对象, 也只会执行一次初始化__init__
    
    class Singleton(object):
        __obj = None
        __init_flag = None
    
        def __init__(self, name):
            if not Singleton.__init_flag:
                print('This is Singleton.')
                self.name = name
                Singleton.__init_flag = True
    
        def __new__(cls, *args, **kwargs):
            if cls.__obj is None:
                cls.__obj = object.__new__(cls)
    
            return cls.__obj
    
    obj1 = Singleton('Aaron')
    obj2 = Singleton('Joe')
    print(obj1.name)
    print(obj2.name)
    
    # 输出结果
    This is Singleton.
    Aaron
    Aaron
    

    6. 面向对象三大特征

    6.1 封装

    对类中成员属性和方法的保护,控制外界对内部成员的访问、修改、删除等操作。

    6.2 继承

    一个类除了自身所拥有的属性方法之外,还获取了另一个类的成员属性和方法。

    6.3 多态

    不同的子类对象,调用相同的父类方法,产生不同的执行结果。

  • 相关阅读:
    python中的归并排序
    使用委派取代继承
    ffmpeg 2.3版本号, 关于ffplay音视频同步的分析
    Java学习之路(转)
    怎样通过terminal得到AWS EC2 instance的ip
    让面试官对你“一见钟情”
    Html5 中获取镜像图像
    架构师速成6.3-设计开发思路
    【转】Android的权限permission
    【转】 Android 基于google Zxing实现对手机中的二维码进行扫描--不错
  • 原文地址:https://www.cnblogs.com/aaron-zhou/p/12003149.html
Copyright © 2011-2022 走看看