• python之路-day19-面向对象之约束


    一、上次内容回顾

    1、反射

      1、hasattr(对象,属性(字符串))

      2、getattr(对象,属性(字符串))

      3、setattr(对象,属性,值)

      4、delattr(对象,属性)

    2、issubclass ,type , isinstance

      issunclass,判断xxx对象或者类是否是xxx的子类

      type:获取xxx对象的数据类型

      isinstance:判断xxx对象是否是xxx类型(向上查找)

    3、方法和

      类外面写的函数都是函数

      在类中:

        实例方法:

          1、类名.方法()  函数

          2、对象.方法()  方法

        类方法:

          都是方法

        静态方法

          都是函数

    4、md5

      特点:不可逆

      加盐

      import hashlib

      obj = hashlib.md5(盐)

      obj.update(byte类型的明文)

      result = obj.hetdidest()

    二、类的约束
    类的约束,主要是为了定义一个父类,约束下面子类必须按照规则
    完成父类中的功能(父类中的功能为空白)
    在python中有两种办法来解决这样的问题
    1、提取父类。然后再父类中定义好方法。在这个方法中什么都不用干,抛一个异常
    就可以了。这样所有的子类都必须重写这个方法。否则,访问的时候报错
    2、使用元类来描述父类。在元类中给出一个抽象方法。这样子类就不得不给出抽象方法
    的具体实现。也可以起到约束的效果

    第一套方案示例:

    class Base:
        def login(self):
            raise Exception("你没有实现login⽅法()")
    class Normal(Base):
        def login(self):
            pass
    class Member(Base):
        def denglu(self):
            pass
    class Admin(Base):
        def login(self):
            pass
    # 项⽬经理写的总⼊⼝
    def login(obj):
        print("准备验证码.......")
        obj.login()
        print("进⼊主⻚.......")
    n = Normal()
    m = Member()
    a = Admin()
    login(n)
    login(m) # 报错.
    login(a)
    
    
      在执行到login(m)那一步程序报错,原因是该类没有login方法,导致去
    访问父类的login方法,抛出异常报错
    Exception异常,是所有异常的根。我们无法通过这个异常来判断出程序
    是因为什么报的错。所以,最好是换一个比较专业的错误信息,换成NotlmplementError
    意为:没实现的错误
     
    第二套方案:写抽象类和抽象方法
    from abc import ABCMeta, abstractmethod
    # 类中包含了抽象⽅法. 那此时这个类就是个抽象类. 注意: 抽象类可以有普通⽅法
    class IGame(metaclass=ABCMeta):
        # ⼀个游戏到底怎么玩⼉? 你能形容? 流程能⼀样么?
        @abstractmethod
        def play(self):
            pass
        def turn_off(self):
            print("破B游戏不玩了, 脱坑了")
    class DNFGame(IGame):
        # ⼦类必须实现⽗类中的抽象⽅法. 否则⼦类也是抽象类
        def play(self):
            print("dnf的玩⼉法")
    # g = IGame() # 抽象类不能创建对象
    dg = DNFGame()
    dg.play()
    
    
          通过代码我们能发现. 这⾥的IGame对DNFGame进⾏了约束. 换句话说. ⽗类对⼦类进
        ⾏了约束.
    
        接下来. 继续解决我们⼀开始的问题.
    
    from abc import ABCMeta, abstractmethod
    class Base(metaclass=ABCMeta):
        @abstractmethod
        def login(self):
            pass
    class Normal(Base):
        def login(self):
            pass
    class Member(Base):
        def denglu(self): # 这个就没⽤了
            pass
        def login(self): # ⼦类对⽗类进⾏实现
            pass
    class Admin(Base):
        def login(self):
            pass
    # 项⽬经理写的总⼊⼝
    def login(obj):
        print("准备验证码.......")
        obj.login()
        print("进⼊主⻚.......")
    
    n = Normal()
    m = Member()
    a = Admin()
    login(n)
    login(m)
    login(a)
    
    
    总结: 约束. 其实就是⽗类对⼦类进⾏约束. ⼦类必须要写xxx⽅法. 在python中约束的
    ⽅式和⽅法有两种:
    1. 使⽤抽象类和抽象⽅法, 由于该⽅案来源是java和c#. 所以使⽤频率还是很少的
    2. 使⽤⼈为抛出异常的⽅案. 并且尽量抛出的是NotImplementError. 这样比较专
    业, ⽽且错误比较明确.(推荐)
     
     
    三、异常处理

    上来先制造个异常:

    def chu(a, b):
        return a/b
    ret = chu(10, 0)
    print(ret)
    
    结果:
    Traceback (most recent call last):
     File "/Users/sylar/PycharmProjects/oldboy/⾯向对象/day05.py", line 100, in
    <module>
     ret = chu(10, 0)
     File "/Users/sylar/PycharmProjects/oldboy/⾯向对象/day05.py", line 98, in
    chu
     return a/b
    ZeroDivisionError: division by zero
    
          什么错误呢. 除法中除数不能是0. 那如果真的出了这个错. 你把这⼀堆信息抛给客户
        么? 肯定不能. 那如何处理呢?
    
    def chu(a, b):
        return a/b
    try:
        ret = chu(10, 0)
        print(ret)
    except Exception as e:
        print("除数不能是0")
    
    结果:
    除数不能是0
    那try...except是什么意思呢? 尝试着运⾏xxxxx代码. 出现了错误. 就执⾏except后⾯的
    代码. 在这个过程中. 当代码出现错误的时候. 系统会产⽣⼀个异常对象. 然后这个异常会向
    外抛. 被except拦截. 并把接收到的异常对象赋值给e. 那这⾥的e就是异常对象. 那这⾥的
    Exception是什么? Exception是所有异常的基类, 也就是异常的跟. 换句话说. 所有的错误都
    是Exception的⼦类对象. 我们看到的ZeroDivisionError 其实就是Exception的⼦类. 那这样
    写好像有点⼉问题撒. Exception表示所有的错误. 太笼统了. 所有的错误都会被认为是Exception.
    当程序中出现多种错误的时候, 就不好分类了, 最好是出什么异常就⽤什么来处理. 这样就更加合理了.
    所以在try...execpt语句中. 还可以写更多的except
    import traceback
    # 计算a+b
    def cul(a, b):
        if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
            return a + b
        else:
            # 在这里有两种方案. 1. 直接返回 , 2. 抛出异常
            # raise 抛出 Exception 错误和异常,所有错误的根
            raise Exception("我要的不是这个. 你应该我传递int或者float")
    
    
    try:
        print(cul(1, "胡辣汤")) # 加上异常的处理
    except Exception as e:
        # 获取到错误信息. 我们需要访问堆栈信息
        print(traceback.format_exc()) # 获取堆栈信息
        print("出现了错误")
    
    
    我们出现的错误. python中没有给出具体的记录, 慎用. 名字一定要符合规范
    JackException 一个让人无从得知的自定义异常,切记慎用自定义异常
    自定义异常
    class GenderException(Exception):
        pass
    
    class Person:
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    
        #  洗澡 -> 男的进男浴室
        def goto_nan_yushi(self):
            if self.gender != "":
                raise GenderException("性别不对") # 除了名字以外都是父类中的Exception
            else:
                print("欢迎光临.")
    try:
        p2 = Person("wusir", "")
        p2.goto_nan_yushi()
        p1 = Person("alex", "")
        p1.goto_nan_yushi()
    except GenderException as e:
        print("你去男澡堂子干嘛?")
    except Exception as e:
        print("其他错误")
     
    
    
    四、日志处理
    import logging
    # filename: ⽂件名
    # format: 数据的格式化输出. 最终在⽇志⽂件中的样⼦
    # 时间-名称-级别-模块: 错误信息
    # datefmt: 时间的格式
    # level: 错误的级别权重, 当错误的级别权重⼤于等于leval的时候才会写⼊⽂件
    logging.basicConfig(filename='x1.log',
         format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
         datefmt='%Y-%m-%d %H:%M:%S',
    level=30)
    # 当前配置表示 0以上的分数会被写⼊⽂件
    # CRITICAL = 50
    # FATAL = CRITICAL
    # ERROR = 40
    # WARNING = 30
    # WARN = WARNING
    # INFO = 20
    # DEBUG = 10
    # NOTSET = 0
    logging.critical("我是critical") # 50分. 最贵的
    logging.error("我是error") # 40分
    logging.warning("我是warning")
    logging.info("我是info")
    logging.debug("我是debug")
    logging.log(1, "我什么都不是")
    
    import traceback
    try:
        print(1/0)
    except Exception:
        logging.error(traceback.format_exc()) # 用法
        print("出错了")
    
    
    
    import logging
    # 创建⼀个操作⽇志的对象logger(依赖FileHandler)
    #                       open()
    file_handler = logging.FileHandler('zuo.log', 'a', encoding='utf-8')
    file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
    logger1 = logging.Logger('qq', level=20)
    logger1.addHandler(file_handler) # 把文件助手和日志对象绑定
    logger1.error('我是A系统出错了') # 记录日志
    
    
    # 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
    file_handler2 = logging.FileHandler('you.log', 'a', encoding='utf-8')
    file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
    logger2 = logging.Logger('B系统', level=20)
    logger2.addHandler(file_handler2)
    
    
    import traceback
    try:
        print(1/0)
    except Exception:
        logger2.critical(traceback.format_exc())
        print("出错了. 请联系管理员")
    print("程序继续知悉个")
    
    
    
    
    from types import MethodType, FunctionType
    class Foo:
        @classmethod
        def func1(self):
            pass
        @staticmethod
        def func2(self):
            pass
        def func3(self):
            pass
    
        def func4(self):
            pass
    
    obj = Foo()
    lst.append(obj.func4)
    for item in lst:
        print(isinstance(item, MethodType))
    
    
    









  • 相关阅读:
    牛客练习赛53 B题调和级数
    装备购买(线性基)
    杨氏矩阵与勾长公式
    南昌邀请赛B题(拉格朗日插值)
    徐州网络赛补题
    __int128 输入输出模板
    51 nod1067 Bash游戏 V2(sg函数打表)
    堆优化的dijkstra算法
    ST表求区间最值
    Tree Reconstruction
  • 原文地址:https://www.cnblogs.com/alvin-jie/p/9948762.html
Copyright © 2020-2023  润新知