+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2019-07(2)

2019-08(106)

2019-09(110)

2019-10(14)

2019-11(8)

Python 高级编程技巧——深入类和对象

发布于2020-06-25 20:27     阅读(473)     评论(0)     点赞(27)     收藏(5)


0

1

2

3

4

5

6

Python 高级编程技巧——深入类和对象

1 深入类和对象

1.1 鸭子类型与多态

鸭子类型

  • 多态的概念四运用于Java 和 C# 这一类型语言中,而Python 崇尚鸭子类型。
a=[1,2]
b=[3,4]
c=[5,6]
d=['abc']
a.extend(b)
a.extend(c)
a.extend(d)
print(a)

class Cat(object):
    def info(self):
        print('i am cat')

class Dog(object):
    def info(self):
        print('i am dog')

class Duck(object):
    def info(self):
        print('i am duck')

animal_list=[Cat,Dog,Duck]
for animal in animal_list:
    animal().info()
  • 鸭子类型 在运行之前,Cat Dog 都是在列表里面,当作变量。
  • 当运行时,加上 () 调用info 才明确 Cat 是一个类。

多态

  • 定义时的类型和运行时的类型不一致,就称为多态

1.2 抽象基类(abc模块)

  • 抽象基类(abstract base class ABC):抽象基类就是类定义了纯虚成员函数的类,纯虚函数只提供了接口,并没有具体实现·,抽象基类不能被实例化(不能创建对象),通常是作为基类供子类继承,子类中重写虚函数,实现具体的接口。
  • 抽象基类就是定义各种方法而不做具体实现的类,任何继承自抽象其类的类必须实现这些方法,否则无法实例化。

抽象基应用场景

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

检查某个类中是否有某种方法

  • 定义Demo类,类中含有__len__魔法方法
  • 导入抽象基类中的 Sized 类
class Demo(object):
    def __init__(self,li):
        self.li=li

    def __len__(self):
        return len(self.li)

l=['C','凌云','九折']

d=Demo(l)

print(d)  # <__main__.Demo object at 0x00000294FD5782E8>

print(len(d))  # 会触发__len__ return len(self.li)  所以返回3

#如何判断 Demo 中是否含有__len__魔法方法
print(hasattr(d,'__len__'))  # 判断  d 的内部 是否含有__len__

from collections.abc import Sized

#判断d 是否是 Sized 这个类
print(isinstance(d,Sized))  # True  说明 d 是Sized 类型

#可以通过判断 d 是都是 Sized 的子类  然后进一步判断 d这个对象的类  是否含有 __len__方法`

注意

  • 抽象基类虽然可以成为别的类的父类,但是别的类并不会继承抽象基类的方法和属性

强制子类必须实现父类的方法

例子

  • 定义父类Cache
    • 封装CRUD,强制子类重写该方法
  • 定义子类Redis
class CacheBase(object):
    def dele(self):
        print('我是dele 方法 ')

    def crea(self):
        print('我是 crea 方法')

class RedisBase(CacheBase):
    pass

r=RedisBase()
r.crea()

class CacheBase(object):
    def dele(self):
        print('我是dele 方法 ')
        raise NotImplementedError
    def crea(self):
        print('我是 crea 方法')
        raise NotImplementedError
class RedisBase(CacheBase):
    # 子类 如果不重写 父类 方法 访问时  直接抛出异常
    def dele(self):
        print('我是dele 方法 ')
    def crea(self):
        print('我是 crea 方法')
r=RedisBase()
r.crea()
r.dele()

import abc
#注意 不是直接继承object  而是 继承abc.ABCMeta

class CacheBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def dele(self):
        pass

    def crea(self):
        pass

class ReadisBase(CacheBase):
    def dele(self):

        pass

r=ReadisBase()  # 这里 如果不重写父类中的方法,直接抛出异常
  • 抽象基类 : 实例化得时候检测
  • 主动抛出异常:调用时才会检测

1.3 type 与 isinstance 区别

  • type 不考虑 继承关系
  • isinstance 考虑继承关系
a=1
b='ni hao'
print(isinstance(a,(int,str))) # 返回值为布尔值
print(type(a))    #  <class 'int'>  返回值是一个类

class Father(object):
    pass

class Son(Father):
    pass

ls=Son()
print(isinstance(ls,Son))     #  True
print(isinstance(ls,Father))  #  True  继承

print(type(ls) is Son)  # True
print(type(ls) is Father)  # False

print(f'Son_id:{id(Son)},Fathon_id:{id(Father)}')

1.4 类属性与实例属性

基本查找顺序

  • 对象是可以向上查找的,所以可以访问到类属性
    • 当对象自己有该实例属性时,则输出是自己的
  • 类不能向下查找,所以只能访问到类属性
class Fathon(object):
    # 类属性
    cls_ins=1

    def __init__(self,a,b):
        # 实例属性
        self.a=a
        self.b=b
       # self._cls_ins=886


zs=Fathon(3,4)
print(zs.cls_ins,zs.a,zs.b)  # 1 3 4

print(Fathon.cls_ins)  # 1

print(Fathon.a)  # AttributeError: type object 'Fathon' has no attribute 'a'

#对象 可以向上查找  可以访问到 类属性
#类不能向下查找  所以 只能访问到类属性  类名.实例属性

Fathon.cls_ins=778
zs.cls_ins=886    # 相当于封装
print(Fathon.cls_ins)
print(zs.cls_ins)

class MyText():
    ins='cls_ins'
    def __init__(self):
        self.ins='ins'

t=MyText()
print(MyText.ins) # cls_ins
print(t.ins)  # ins
  • 当对象 自己有该实例属性的时候 就直接输出自己的
  • 当对象 自己没有该属性的时候,才会向类 向上查找

多重继承查询顺序

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

class B(D):
    pass

class C(D):
    pass

class A(B,C):
    pass
print(A.__mro__)  
# (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>

1.5 Python 对象自省机制

  • 自省是通过一定的机制查询到对象的内部结构
  • Python 中比较常见的自省(introduction)机制(函数用法)有:dir(),type(),hasattr(),isinstance(),通过这些函数,我们能够在程序运行时得知对象的类型,判断对象是否存在某个属性,访问对象的属性。
class Person(object):
    name='会太阳'

class Student(Person):
    def __init__(self,school_name):
        self.school_name=school_name

hty=Student('Logic_edu')
print(hty.__dict__)    # {'school_name': 'Logic_edu'}  当前对象的属性{‘属性’:'属性'}
print(dir(hty))  # 返回 [ ]  考虑到继承的成员

super函数

  • 多继承下,super函数查询父类的顺序如何?
class A(object):
    def __init__(self):
        print('A')

class C(A):
    def __init__(self):
        print('B')
        super().__init__()

class B(A):
    def __init__(self):
        print('C')
        super().__init__()

class D(B,C):
    def __init__(self):
        print('D')
        super().__init__()

if __name__=='__main__':
    d=D()
    print(D.__mro__)
    
'''
D
C
B
A
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)'''
  • 多重继承下,super函数查询父类的顺序依次从下往上查询。

原文链接:https://blog.csdn.net/weixin_44864954/article/details/106909315

0

1

2

3

4

5

6

7

8

9



所属网站分类: 技术文章 > 博客

作者:9384vfnv

链接: https://www.pythonheidong.com/blog/article/430414/07e2073185f08dbce082/

来源: python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

27 0
收藏该文
已收藏

评论内容:(最多支持255个字符)