python 深入类和对象

1. 鸭子对象和多态

1.1 鸭子类型

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

  • 示例代码
    class duck:
        def say(self):
            print("I am a duck")
    
    
    class dog:
        def say(self):
            print("I am a dog")
    
    
    class cat:
        def say(self):
            print("I am a cat")
    
    
    duck().say()
    dog().say()
    cat().say()
    
    
    从上面的代码可以知道,dog类、cat类都不是鸭子,但是他们和duck类很像,都有say这个方法。

1.2 多态

  • 什么是多态?
    在需要使用父类对象的地方,也可以使用子类对象, 这种情况就叫多态.
    比如, 在函数中,我需要调用 某一个父类对象的方法, 那么我们也可以在这个地方调用子类对象的方法.
  • 如何在程序中使用多态?
    可以按照以下步骤实现代码:
    1、子类继承父类
    2、子类重写父类中的方法
    3、通过对象调用这个方法
    
  • 示例代码
    class Father:
        def repair(self):
            print("父亲在修理...")
    
    
    class Son(Father):
        def repair(self):
            print("儿子在修理...")
    
    
    father = Father()
    father.repair()
    
    son = Son()
    son.repair()
    
    

2. 抽象基类

2.1 抽象基类介绍

抽象类(abstract base class,ABC)就是类里定义了纯虚成员函数的类。纯虚函数一般只提供了接口,并不会做具体实现(虽然可以),实现由它的派生类去重写。抽象类不能被实例化(不能创建对象),通常是作为基类供子类继承,子类中重写虚函数,实现具体的接口。简言之,ABC描述的是至少使用一个纯虚函数的接口,从ABC派生出的类将根据派生类的具体特征,使用常规虚函数来实现这种接口。

2.2 抽象基类应用场景

• 1.我们去检查某个类中是否有某种方法
• 2.我们需要强调某个子类必须实现某些方法
1.检查某个类中是否有某种方法

  • 示例代码
    class Demo:
        def __init__(self, x):
            self.x = x
    
        def __len__(self):
            return self.x
    
    
    demo = Demo("abcd")
    
    # 导入基类的Size
    from collections.abc import Sized
    
    # 判断是否含有某种方法
    print(isinstance(demo, Sized))  # True,demo是Size的子类
    
    

2.我们需要强调某个子类必须实现某些方法

  • 示例代码
    import abc
    
    
    class A(metaclass=abc.ABCMeta):
        # 定义一个抽象方法
        @abc.abstractclassmethod
        def dem(self):
            pass
    
    
    class B(A):
        # 这里必须继承父类的dem的抽象方法,否则在下面实例化的时候会报错
        def dem(self):
            pass
    
    
    b = B()
    
    

注意: 如果python版本在3.3以上,则可以使用@classmethod代替@abc.abstractclassmethod

3. type与isinstance

3.1 type与isinstance的区别

  • 返回值区别
    • type的返回值是对象的类型
    • isinstance的返回值是Boolean类型
    • 示例代码
       str1 = 'abcd'
       print(type(str1))   # <class 'str'>
       print(isinstance(str1, str))    # True
      
      
  • type与isinstance的区别
    • type() 不会认为子类是一种父类类型,不考虑继承关系。
    • isinstance() 会认为子类子类是一种父类类型,考虑继承关系
    • 示例代码
      class Father:
      	pass
      
      
      class Son(Father):
          pass
      
      
      son = Son()
      print(isinstance(son, Son)) # True
      print(isinstance(son, Father))  # True 考虑继承
      print(type(son) is Son) # True
      print(type(son) is Father)  # False 不考虑继承关系
      
      

4. 类属性与实例属性

4.1 基本查找顺序

  • 对象是可以向上查找的,所以可以访问到类属性
    class Demo:
        temp = '你好'
    
        def __init__(self):
            pass
    
    
    demo = Demo()
    print(demo.temp)    # 输出 你好,说明实例对象可以向上访问类属性
    
    
  • 当对象自己有该实例属性时 ,则输出的是自己的
    class Demo:
      temp = '你好'
    
      def __init__(self):
          self.temp = 'hello'
    
    
      demo = Demo()
      print(demo.temp)  # 输出 hello,说明实例对象有与类属性相同的实例属性时,输出当前的属性值
      
    
  • 类不能向下查找,所以只能访问到类属性
    class Demo:
        temp = '你好'
    
        def __init__(self):
            self.temp = 'hello'
            self.t1 = 'good'
    
    
    demo = Demo()
    print(Demo.t1)  # 报错type object 'Demo' has no attribute 't1',说明类不能向下查找,所以只能访问到类属性
    
    

4.2 多继承查询顺序

继承关系如下,则属性查找顺序为?
在这里插入图片描述
实际上,python2.2(金典类)之前的算法:MRO算法,DFS(deep first search) 深度优先。
在这里插入图片描述
如下图,菱形继承,执行顺序如何?
在这里插入图片描述
在python2.2版本之后,引入BFS(广度优先)。
在python新式类,就引入了C3算法,通过className.__mro__来查看。
在这里插入图片描述

4. Python对象自省机制

自省是通过一定的机制查询到对象的内部结构

Python中比较常见的自省(introspection)机制(函数用法)有: dir(),type(), hasattr(), isinstance(),通过这些函数,我们能够在程序运行时得知对象的类型,判断对象是否存在某个属性,访问对象的属性。

  • 代码示例
    class Perpon(object):
        name = "码农"
    
    
    class Student(Perpon):
        def __init__(self, school_name):
            self.school_name = school_name
    
    
    hty = Student("宇宙学院")
    print(hty.__dict__)  # {'school_name': '宇宙学院'}  当前对象的属性 {"属性":"属性的值"}
    
    print(dir(hty))  # []  考虑到继承的成员
    
    

4.1 super函数

super() 函数是用于调用父类(超类)的一个方法。

  • 代码示例
    class Person(object):
        def __init__(self, name, age, weight):
            self.name = name
            self.age = age
            self.weight = weight
    
        def speak(self):
            print(f"{self.name}说:我{self.age}岁")
    
    
    class Student(Person):
        def __init__(self, name, age, weight, grade):
            # 因为父类已有name,age,weight三个属性,所以不必重新定义
            super().__init__(name, age, weight)
            self.grade = grade
    
        def speak(self):
            print(f"{self.name}说:我{self.age}岁,我在{self.grade}年级")
    
    
    cmy = Student('cmy', 20, 120, 2)
    cmy.speak()
    
    

最后,有喜欢博主写的内容的伙伴可以收藏加关注哦!

猜你喜欢

转载自blog.csdn.net/weixin_44604586/article/details/106779399