zoukankan      html  css  js  c++  java
  • Python Day29:元类、单例模式、异常/异常处理

    ## 元类:
    
    
    
    ```python
    元类:用来创建类的类。类对象都是有type实例化产生的。
    类也是对象,可以把一个类当作普通对象用来使用,必须存储到列表中,或者作为参数传给函数等等...
    元类都继承type
    一个类对象由三部分组成:
    1,类名称;2,类的父类们;3,类的名称空间(字典)
    type的两种语法用法:
        type(类名,父类元组,名称空间字典)  #返回一个新的类
        type(对象)  #将会返回这个对象的类型
    我们在定义一个class时,解释器会自动调用type来完成类的实例化
    # 模拟解释器创建类对象
    def test1(a):
        print(a)
    
    def test2(self,b):
        print(self,b)
    
    class_name = "C"
    bases = (object,)
    name_dict = {"name":"jack","test1":test1,"test2":test2}
    
    C = type(class_name,bases,name_dict)
    # print(C)
    c1 = C()
    # print(c1)
    c1.test2(100)
    
    # 元类翻译为:metaclass  只要看见它就应该想起来这是元类 
    #我们在定义元类时  尽量在类名后添加MetaClass  方便阅读
    例:class MyMetaClass(type):
        pass
    #使用自定义元类
    class Person(metaclass=MyMetaClass):
        pass
    
    #***__init__`方法 (重点)***
    实例化对象时会自动执行类中的`__init__`方法, 类也是对象 ,在实例化类对象时会自动执元类中的`__init__`方法
    并且传入类的三个必要参数:"类的名字,父类们,名称空间"
    当然会自动传入类对象本身作为第一个参数  
    #__new__方法
    元类中的new方法会在创建类对象时执行,并且先于init方法!
    "其作用是创建一个类对象  
    1.执行MyMetaClass的`__new__`方法   拿到一个类对象 
    2.执行MyMetaClass的`__init__` 方法  传入类对象以及其他的属性 ,进行初始化
    
    注意:如果覆盖了`__new__` 一定也要调用type中的`__new__`并返回执行结果   否则无法创建类对象!
        
    #就算__init__中什么都不写 这个类对象其实已经创建完成了 该有的属性都有了,因为创建类对象的时候先执行__new__来产生空对象。
    #为什么普通类不调用__new__,因为普通类没有这三个属性
    # 这是与普通类不同之处
        
        
    # 使用new方法也可以完成定制类的工作  和init有什么区别?
    在调用init方法前类对象已经创建完成了   
    所以如果对性能要求高的话 可以选在在new中完成定制   如果发现有问题,就不用创建类对象了,节省运行时的内存空间
    
    
    
    #***__call__`方法(重点)***
    元类中的 call方法会在调用类时执行,或类对象被实例化时执行
    可以用于控制对象的创建过程
    # 注意注意注意:  __new__  __init__ 是创建类对象时还会执行
    
    __init__:多用于控制类的三个元素:类名、类的父类、类的字典
    __call__:多用于控制类在创建对象时,控制实参的。
    
    ```
    
    ## 单列模式
    
    ```python
    单列模式:某个类如果只有一个实例对象,那么该类成为单例类 
    单例的好处:当某个类的所有对象特征和行为完全一样时,避免重复创建对象,浪费资源
    #思考:只有一个实例对象的类,对类的实例对象进行控制,就意味着要考虑__call__方法。
    
    例:
    class SingletonMetaClass(type):
        #创建类时会执init 在这为每个类设置一个obj属性 默认为None
        def __init__(self,a,b,c):
            super().__init__(a,b,c)
            self.obj = None
        
        # 当类要创建对象时会执行 该方法
        def __call__(self, *args, **kwargs):
             # 判断这个类 如果已经有实例了就直接返回 从而实现单例
            if self.obj:
                return self.obj
            # 没有则创建新的实例并保存到类中
            self.obj = type.__call__(self,*args,**kwargs)
            return self.obj
    
    
    ```
    
    ## 异常
    
    
    
    ```python
    异常是程序运行过程中发生的非正常情况,是一个错误发生时的信号
    异常如果没有被正确处理的话,将导致程序被终止,这对于用户体验是非常差的,可能导致严重的后果  
    处理异常的目的就是提高程序的健壮性 
    ### 异常的分类
    python解释器在执行代码前会先检查语法,语法检查通过才会开始执行代码
    1.语法检测异常  作为一个合格的程序员 是不应该出现这种低级错误 
    2.运行时异常   已经通过语法检测,开始执行代码,执行过程中发生异常 称之为运行时异常
    
    异常的组成:
    Traceback (most recent call last):
      File "F:/python8期/课堂内容/day29/11.常见异常.py", line 22, in <module>
        with open("xxxxx") as f:
    FileNotFoundError: [Errno 2] No such file or directory: 'xxxxx'
            
    Traceback    是异常追踪信息   用于展示错误发生的具体位置 以及调用的过程
    其中 包括了 错误发生的模块  文件路径   行号  函数名称  具体的代码
    
    最后一行  前面是错误的类型  
             后面 错误的详细信息   在查找错误时 主要参考的就是详细信息
        
    # 重点:
    必须掌握的语法
    语法:
    try:
    可能会出现异常的代码 放到try里面
    except 具体异常类型(或者万能异常类型Exception)as e:
    如果真的发生异常就执行except 
    
    自定义异常类型:当系统提供异常类不能准确描述错误原因时   就可以自定义异常类  
    继承自Exception即可 class  MyException(Exception):  pass
    
    主动抛出异常:
    什么时候需要主动抛出异常  
    当我们做功能的提供者,给外界提供一个功能接口
    但是使用者不按照相应的方式来使用,或者参数类型不正确等原因,导致功能无法正常执行时,就应该主动抛出异常
    主动抛出异常使用raise  关键字 
    raise MyException
    raise MyException("错误具体原因!")
    
    ```
    
    # 如何正确处理异常
    
    1. 当发生异常  不是立马加try   要先找出错误原因并解决它  
    
    2. try 仅在 即使你知道为什么发生错误 ,但是你却无法避免  
       例如   你明确告诉用户 需要一个正确文件路径 然而用户依然传入了错误的路径   
    
       如  socket    双方都要使用管道  ,但是如果一方有由于某些原因强行关闭了 ,即使你知道原因也无法避免出错   那就只能try 保证程序正常结束      
    
       总结一句话:能不加try 就不加try
    
       
  • 相关阅读:
    Servlet梳理一
    String和StringBuffer的区别
    谈谈面对将要来到的第一份工作
    shell grep文本搜索
    Shell cut分割
    python的学习之路:计算
    web端和手机端测试有什么不同
    让TortoiseGit记住帐号密码方法
    操纵IE,模拟用户登录
    MVC路由配置.html不能识别
  • 原文地址:https://www.cnblogs.com/huhongpeng/p/10924103.html
Copyright © 2011-2022 走看看