• python面向对象其他相关-异常处理-反射


    1.isinstance(obj, cls)

    检查是否obj是否是类 cls 的对象

    2.issubclass(sub, super)

    检查sub类是否是 super 类的派生类

    n1 = 10
    a1 = "123"
    print type(n1)
    print type(a1)
    print isinstance(n1,int)            #判断n1是否属于int类型,正确返回True
    print '-->',isinstance(n1,str)      #判断n1是否属于str类型,正确返回True
    
    class A:
        pass
    class B(A):
        pass
    a = B()
    print isinstance(a,A)
    print isinstance(a,B)
    print issubclass(B,A)   #检查B类是不是A类的派生类
    print issubclass(A,B)
    
    
    执行结果:
    <type 'int'>
    <type 'str'>
    True
    --> False
    True
    True
    True
    False

    3.异常处理

    异常基础:

    try:
        pass
    except Exception,e:
        print e  #打印出异常内容
        pass

    实例:

    while True:
        num1 = raw_input('num1:')
        num2 = raw_input('num2:')
        try:
            num1 = int(num1)    #将输入内容转换为int类型
            num2 = int(num2)
            result = num1 + num2
        except Exception, e:
            print '出现异常,信息如下:'    #当输入不为int类型,捕获异常
            print e
    
    #运行
    num1:1
    num2:2
    num1:d
    num2:
    3出现异常,信息如下:
    invalid literal for int() with base 10: 'd'
    num1:1.1
    num2:2
    出现异常,信息如下:
    invalid literal for int() with base 10: '31.1'
    在实际应用中,我们可能需要捕获一些特定的异常,最后的时候才捕获所有异常类型
    #常用异常
    AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
    IOError 输入/输出异常;基本上是无法打开文件
    ImportError 无法引入模块或包;基本上是路径问题或名称错误
    IndentationError 语法错误(的子类) ;代码没有正确对齐
    IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
    KeyError 试图访问字典里不存在的键
    KeyboardInterrupt Ctrl+C被按下
    NameError 使用一个还未被赋予对象的变量
    SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
    TypeError 传入对象类型与要求的不符合
    UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
    ValueError 传入一个调用者不期望的值,即使值的类型是正确的

    IndexError示例:

    dic = ["ares", 'aaaa']
    try:
        dic[10]
    except KeyError,e:
        print e
    
    #执行结果报错为
      File "XXX", line 6, in <module>
        dic[10]
    IndexError: list index out of range
    
    #更改捕获的错误类型
    dic = ["ares", 'aaaa']
    try:
        dic[10]
    except IndexError, e:
        print e
    
    #此时运行就捕获到了错误类型
    list index out of range

    KeyError示例:

    dic = {'k1':'v1'}
    try:
        dic['k2']
    except KeyError, e:
        print e
    
    #捕获到的错误类型
    'k2'

    ValueError示例:

    s1 = 'hello'
    try:
        int(s1)
    except ValueError, e:
        print e
    
    #捕获到的错误
    invalid literal for int() with base 10: 'hello'

    如果是单纯的定义一个异常,则如果程序中出现其他异常就会报错,此时,我们可以捕获已知的异常类型,对于未知的异常类型可以用万能异常 Exception捕获。

    s1 = 'hello'
    try:
        int(s1)
    except KeyError,e:
        print '键错误'
    except IndexError,e:
        print '索引错误'
    except Exception, e:
        print '错误'

    异常结构:

    try:
        #逻辑代码
        pass
    except IndexError,e:
        pass
    except Exception,e:
        pass
    else:
        #逻辑串中未出现异常
        pass
    finally:
        #释放资源,断开连接
        #永远执行,逻辑代码执行完之后执行
        pass

    有时我们可能想要主动触发异常,方法如下

    try:
        raise Exception('错误了。。。')
    except Exception,e:
        print e
    
    #输出结果
    错误了。。。

    自定义异常:

    #自定义异常
    class OwnerError(Exception):
        def __init__(self,msg=None):
            self.message = msg
        def __str__(self):
            if self.message:
                return self.message
            else:
                return 'Owner Error'
    try:
        raise OwnerError('erroreroor')
    except Exception,e:
        print e
    
    #输出内容
    erroreroor

    断言:

    # assert 条件
    assert 1 == 1
    assert 1 == 2
    
    #不太清楚,先记下

    重头戏,反射来了。。。。。

    python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。

    示例1:输入不同url来实现不同跳转

    #home.py函数
    def dev():
        return "home/dev"
    def index():
        return "home/index"
    def login():
        return "home/login"
    def logout():
        return "home/logout"
    
    #调用home模块
    import home
    #输入不同url跳转
    #第一种实现方式,使用if/else做判断
    print "-------------------->"
    while True:
        url = raw_input("input url:")
        if url == "home/dev":
            ret = home.dev()
            print ret
        elif url == "home/index":
            ret = home.index()
            print ret
        elif url == "home/login":
            ret = home.login()
            print ret
        elif url == "home/logout":
            ret = home.logout()
            print ret
        else:
            print "404"
    
    #运行结果
    -------------------->
    input url:home/dev
    home/dev
    input url:home/login
    home/login
    input url:home/sad
    404
    可以看到,上述代码已经基本实现了我们的需求,即输入不同url来进行不同的跳转,但是,如果url有上万个,这么方式显然是不可取的,那么,应该怎么办呢???

    其实,将上述代码稍作修改即可:

    #第二种实现方式,使用getattr函数做反射
    import home
    print "-------------------->"
    while True:
        url = raw_input("input url:")
    #对输入的url从/进行切割,例如输入home/dev,那么controller即为home,function为dev
        controller,function = url.split('/')    
        #function为字符串
        #去某个函数(模块)中找函数,字符串函数名,若果有则获取函数
        func = getattr(home,function)
        ret = func()
        print ret

    实例2:

    #getattr,setattr,deleattr,hasattr,对内存某一个容器的元素做操作,只对内存做更改
    #找到home文件,加载到内存
    import home
    print dir(home)
    print hasattr(home,'dev')   #判断home里是否存在dev方法
    print hasattr(home,'devv')
    print getattr(home,'dev')   #取出home里是否存在dev方法
    setattr(home,'ares','single')       #设置ares成员
    print dir(home)
    setattr(home,'ares',lambda x:x+1)
    print dir(home)
    delattr(home,'ares')        #删除ares成员
    print dir(home)
    
    #执行结果
    ['__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'dev', 'index', 'login', 'logout']
    True
    False
    <function dev at 0x00000000027A1978>
    ['__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'ares', 'dev', 'index', 'login', 'logout']
    ['__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'ares', 'dev', 'index', 'login', 'logout']
    ['__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'dev', 'index', 'login', 'logout']

    实例3:

    class Foo:
        atatic_name = 'ares'
        def __init__(self):
            self.name = 'ares'
        def show(self):
            pass
        @staticmethod
        def static_show():
            pass
        @classmethod
        def class_show(self):
            pass
    
    print Foo.__dict__.keys()
    print hasattr(Foo,'static_show')
    obj = Foo()
    print obj.__dict__
    print obj.__dict__['name']      #将获取obj对象中的name变量指向内存中的值 “ares”
    print hasattr(obj,'name')
    print hasattr(obj,'show')
    print getattr(obj,'name')       #将获取obj对象中的name变量指向内存中的值 “ares”
    
    #执行结果
    ['atatic_name', '__module__', 'static_show', 'show', 'class_show', '__doc__', '__init__']
    True
    {'name': 'ares'}
    ares
    True
    True
    ares

    web框架实例,可在浏览器执行localhost:8001/xxx:

    from wsgiref.simple_server import make_server
    def RunServer(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        url = environ['PATH_INFO']
        temp = url.split('/')[1]            #获取http://localhost:8001/login的login字符串
        import home
        is_exist = hasattr(home, temp)      #去home模块中检查是否含有指定的函数
        if is_exist:                        #如果存在指定函数
            func = getattr(home, temp)      #获取函数
            ret = func()                    #执行函数并获取返回值
            return ret                     #将函数返回值相应给请求者
        else:
            return '404 not found'
    
    if __name__ == '__main__':
        httpd = make_server('', 8001, RunServer)
        print "Serving HTTP on port 8001..."
        httpd.serve_forever()

    一切事物皆对象,类是对象,模块也是对象!

    单例模式:

    demo:

    from wsgiref.simple_server import make_server
    class DbHelper(object):
        def __init__(self):
            self.hostname = '1.1.1.1'
            self.port = 3306
            self.password = 'pwd'
            self.username = 'root'
        def fetch(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            return 'fetch'
        def create(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            return 'create'
        def remove(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            return 'remove'
        def modify(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            return 'modify'
    
    class Handler(object):
        def index(self):
            # 创建对象
            db = DbHelper()
            db.fetch()
            return 'index'
        def news(self):
            return 'news'
    
    def RunServer(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        url = environ['PATH_INFO']
        temp = url.split('/')[1]
        obj = Handler()
        is_exist = hasattr(obj, temp)
        if is_exist:
            func = getattr(obj, temp)
            ret = func()
            return ret
        else:
            return '404 not found'
    
    if __name__ == '__main__':
        httpd = make_server('', 8001, RunServer)
        print "Serving HTTP on port 8001..."
        httpd.serve_forever()

    上述实例,每个请求到来,都需要在内存里创建一个实例,再通过该实例执行指定的方法。如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。存在这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用,这么可以省下不少的内存。

    单实例模式就是用来解决这个问题的,单例模式用来保证内存中仅存在一个实例!!!

    对于Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.singleton() ,上述代码可以修改成

    #!/usr/bin/env python
    #coding:utf-8
    from wsgiref.simple_server import make_server
    
    # ########### 单例类定义 ###########
    class DbHelper(object):
    
        __instance = None
    
        def __init__(self):
            self.hostname = '1.1.1.1'
            self.port = 3306
            self.password = 'pwd'
            self.username = 'root'
    
        @staticmethod
        def singleton():
            if DbHelper.__instance:
                return DbHelper.__instance
            else:
                DbHelper.__instance = DbHelper()
                return DbHelper.__instance
    
        def fetch(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            pass
    
        def create(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            pass
    
        def remove(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            pass
    
        def modify(self):
            # 连接数据库
            # 拼接sql语句
            # 操作
            pass
    
    
    class Handler(object):
    
        def index(self):
            obj =  DbHelper.singleton()
            print id(single)
            obj.create()
            return 'index'
    
        def news(self):
            return 'news'
    
    
    def RunServer(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        url = environ['PATH_INFO']
        temp = url.split('/')[1]
        obj = Handler()
        is_exist = hasattr(obj, temp)
        if is_exist:
            func = getattr(obj, temp)
            ret = func()
            return ret
        else:
            return '404 not found'
    
    if __name__ == '__main__':
        httpd = make_server('', 8001, RunServer)
        print "Serving HTTP on port 8001..."
        httpd.serve_forever()

    总结:单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费!

    更多请参考:http://www.cnblogs.com/wupeiqi/articles/5017742.html

  • 相关阅读:
    MySQL数据库高可用集群搭建-PXC集群部署
    高性能高并发网站架构,教你搭建Redis5缓存集群
    redis连接错误3种解决方案System Error MISCONF Redis is configured to save RDB snapshots
    进程异常行为-反弹Shell攻击,KILL多个进程
    Laravel中我们登录服务器通过 Tinker 手动创建后台管理用户
    Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]解决
    Laravel:php artisan key:generate三种报错解决方案,修改默认PHP版本(宝塔面板)
    大型网站如何防止崩溃,解决高并发带来的问题
    PHP微信公众平台OAuth2.0网页授权,获取用户信息代码类封装demo(二)
    iOS开发 ReactiveCocoa入门教程 第二部分
  • 原文地址:https://www.cnblogs.com/aresxin/p/5046923.html
Copyright © 2020-2023  润新知