python学习------------异常以及反射

学完这一节,python基础部分就要告一段落了,期待进入新一阶段的学习,也给自己说坚持就是胜利。

一、isinstance(obj,cls)

检查obj是否是cls的对象

1、首先从学过的变量开始

a = 12
b = "bb"
print isinstance(a,int) #结果是True
print isinstance(a,str) #结果是False
print isinstance(b,str) #结果是True
print isinstance(b,int) #结果是False

其实也就是说:变量a,b是对象,是否是属于int,str的类,属于返回True,不属于返回False

2、类中的对象和类之间的关系

class Foo:
    def __init__(self):
        pass

    def func(self):
        pass

obj = Foo()
print isinstance(obj,Foo) #结果是True

3、对象和基类的关系

class Foo:
    def __init__(self):
        pass

    def func(self):
        pass
class Bar(Foo):
    pass

obj = Bar()
print isinstance(obj,Bar) #结果为True
print isinstance(obj,Foo) #结果是True

总结:

  • isinstance是判断一个对象是否属于类
  • 就是对象和类的关系
  • 对象和基类的关系

二、issubclass(sub,super)

检查sub是否是super的派生类

class Foo:
    def __init__(self):
        pass

    def func(self):
        pass
class Bar(Foo):
    pass

print issubclass(Bar,Foo) #结果为True

三、异常处理

1、产生的缘由

为了在编程过程中,增加和用户交互的友好性,在程序出现错误时不将错误信息显示给用户,也就是不会出现我们通常浏览页面时出现的大黄页,而是显示一个错误提示的界面。

2、在python中处理异常的方法

try:
    pass
except Exception e:
    pass

在try中是正确的逻辑代码

在except中是代码逻辑块出现错误

例如:

input = raw_input("input:")
data = int(input)
try:
    input = raw_input("input:")
    data = int(input)
except Exception,e:
    print "请输入数字"

在一块代码中,加入我输入数字,程序不会报错,而当我输入字母时,程序就会报错。

而在加了try和except块的代码时,当输入数字时,程序依然不会报错,而输入非数字时就会打印提示信息,让你输入数字。

通过以上对比,可以看出加了异常处理的代码比没加异常处理的代码的用户交互的友好性提高了很多。

3、异常的种类

1)、指定的异常

dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘}
try:
    dic[‘k3‘]
except KeyError,e:
       print e
dic = ["tom", ‘bb‘]
try:
    dic[10] 
except IndexError, e:
    print e
#list index out of range
s1 = ‘hello‘
try:
    int(s1)
except ValueError, e:
    print e
#invalid literal for int() with base 10: ‘hello‘

上述代码异常都是指定的是特定的错误处理,例如key,index,value等,但是这样处理也会存在一定的问题,例如:

#假如你写成下面的异常处理,程序未能捕获出异常,程序直接报错
s1 = ‘hello‘
try:
    int(s1)
except IndexError,e:
    print e

针对这样的问题,一般我们处理异常时一般写成如下的异常处理顺序

s1 = ‘hello‘
try:
    int(s1)
except IndexError,e:
    print e
except KeyError,e:
    print e
except ValueError,e:
    print e
except Exception,e:
    print e

也就是说先写特殊的,最后写最终的Exception,Exception也被叫做万能异常,可以捕获任意异常。

但是反过来会说,既然有了万能异常可以捕获任意的异常,还需要特殊异常做什么?

答案是这样的:对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序运行正常。

总结一下特殊的异常

ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError

4、异常的大结构

try:
    #主代码块,逻辑代码
    pass
except IndexError,e:#异常处理
    pass
except Exception,e:
    pass
else:
    #逻辑块中未出现异常,主代码块执行完后执行
    pass
finally:
    #永远执行,逻辑代码执行完后执行
    pass

5、主动触发异常

#导入另外一个模块,然后调用其中的方法
import helper  #helper里有方法f1(),返回一个值
if __name__ == "__main__":
  try:
     n = "1"
     n = int(n)
     IndexError
     ret = helper.f1()
     if ret:
         print "成功"
     else:
         #出现错误
         raise Exception("出现错误")
  except Exception,e:
      print "出现错误"
      print e

如果返回的值为假,则就会主动触发错误,即raise Exception("出现错误")

小结:

1、以上关于异常的处理中,都会有一个e:它的作用是什么?

答案:e是对象,将IndexError等都封装到e中,相当于类中的字段封装的对象中。

2、Exception和这些特殊的处理IndexError是什么关系?

答案:Exception是他们的基类。

3、为什么下面的异常会打印这样的提示?

try:
   int("aa")
except Exception,e:
   print e
#异常结果为:invalid literal for int() with base 10: ‘aa‘

首先给出答案:它是由类中的__str__方法产生的

例如:

class A:
     pass
obj = A()
print obj
#结果为<__main__.A instance at 0x023EF7B0>

这样可以看出我们在异常中print e的结果是一个字符串,而在类中print 对象是内存地址,那怎么做才能和print e一致呢?

class A:
    def __str__(self):
        return "aa"
obj = A()
print obj
#结果为aa

在类中加入__str__方法,再次print 对象,就会打印一个字符串,这就和在异常中打印invalid literal for int() with base 10: ‘aa‘原理一样了。

本质为:在异常中e是对象,而Exception是类,也就是对象e调用类Exception中的__str__方法得到的结果。

6、自定义异常

#类crazyException继承了类Exception
class crazyException(Exception):
    #将msg封装到对象e中
    def __init__(self, msg= None):#初始值msg为None
        self.message = msg

    def __str__(self):
        if self.message:
             return self.message
        else:
             return ‘crazyException‘

try:
    raise crazyException(‘我的异常‘)
except Exception,e:
    print e

7、断言:assert

作用在程序调试时,判断程序是否正确,用于debug

assert 条件

如果条件为真,不会报错,否则,程序报错

例如:

assert 1==1

assert 1==2

四、反射

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

class Foo(object):

    def __init__(self):
        self.name = ‘tom‘

    def func(self):
        return ‘func‘

obj = Foo()

# #### 检查是否含有成员 ####
hasattr(obj, ‘name‘)
hasattr(obj, ‘func‘)

# #### 获取成员 ####
getattr(obj, ‘name‘)
getattr(obj, ‘func‘)

# #### 设置成员 ####
setattr(obj, ‘age‘, 18)
setattr(obj, ‘show‘, lambda num: num + 1)

# #### 删除成员 ####
delattr(obj, ‘name‘)
delattr(obj, ‘func‘)

2、下面通过例子一步步的讨论反射:

1)、我们模拟web为例

home.py

def index():
    return ‘home.index‘

def dev():
    return ‘home.dev‘
import home
url = raw_input("url:")
if url == "home/dev":
    ret = home.dev()
    print ret
elif url == "home/index":
    ret = home.index()
    print ret
else:
    print "404"

这就是说我们输入对应的url,再进行判断找到符合条件的url,返回值

下面我们采用反射来进行操作

url = raw_input("url:")
#url = home/dev
controller,action = url.split(‘/‘)
import home
#action = 字符串
#去某个容器或模块中,找函数,字符串是函数名,如果有,则获取函数
func = getattr(home,action)
#在home中找action,如果有则返回函数名
ret = func()#函数名加括号,表示执行函数,返回结果ret
print ret

这样一来在上面的代码中就不需要再进行判断,只需去在home模块中寻找符合的url,这对于大量的url来说,用反射就简单了。

2)对四种内置函数产生的结果进行比较

import home
print dir(home)#结果为[‘__builtins__‘, ‘__doc__‘, ‘__file__‘, ‘__name__‘, ‘__package__‘, ‘dev‘, ‘index‘]
print hasattr(home,‘dev‘)#结果为True
print getattr(home,‘dev‘)#结果<function dev at 0x026072F0>

setattr(home,‘show‘,lambda x : x + 1)
print dir(home)
#结果为[‘__builtins__‘, ‘__doc__‘, ‘__file__‘, ‘__name__‘, ‘__package__‘, ‘dev‘, ‘index‘, ‘#show‘]
#多了show
delattr(home,‘show‘)
print dir(home)
#结果为[‘__builtins__‘, ‘__doc__‘, ‘__file__‘, ‘__name__‘, ‘__package__‘, ‘dev‘, ‘index‘]
#将show删除了

3)在web上进行测试(练习反射)

#!/usr/bin/env python
#coding:utf-8
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]
    import home
    #去home模块中检查,是否含有指定的函数
    is_exist = hasattr(home, temp)
    #如果存在指定的函数
    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()

3、反射操作类和对象中的成员

class Foo:
    static_name = ‘tom‘
    def __init__(self):
        self.name = "eric"

    def show(self):
        pass
    @staticmethod
    def static_method():
        pass
    @classmethod
    def class_show(cls):
        pass
#先看类中都有什么方法
print Foo.__dict__.keys()
#[‘__module__‘, ‘static_method‘, ‘show‘, ‘static_name‘, ‘class_show‘, ‘__doc__‘, ‘__init__‘]
print hasattr(Foo,‘class_show‘) #看类中是否有class_show方法
obj = Foo()
#看对象中有什么,结果为{‘name‘: ‘eric‘}
print obj.__dict__
print hasattr(obj,‘name‘) #结果为True
print hasattr(obj,‘show‘) #结果为True

为什么对象中只有name,而用hasattr(obj,‘show‘)却显示为True,因为对象中存在类对象指针,对象首先在自己的内存中找,如果没有找到再到类中找,所以就会显示找到,返回结果为True

4、上面的操作都是在自己模块的内部执行,接下来看在其他模块执行效果

import home
cls = getattr(home,‘Foo‘)
print cls #home.Foo 得到是类
obj = cls() #cls是类,类加括号就是实例化,也就是创建对象,执行__init__方法
name = getattr(obj,‘name‘) #在对象中找name
print name

一句话总结反射:在容器中找对象的元素

5、动态导入模块

try:
    controller,action = raw_input("url:").split("/")
    module = __import__(controller)
    func = getattr(module,action)
    ret = func()
    print ret
except Exception,e:
    print "请正确输入url"

五、单例模式

单例就是单个实例

单例模式存在的目的就是保证内存中只存在一个实例,避免内存浪费

用两个例子对比说明单例模式

1、不使用单例模式

class SqlHelper:

    def __init__(self,name):
        self.name = "tom"
        self.name = name

    def show(self):
        pass

obj1 = SqlHelper(1)
print id(obj1) #37025832
obj2 = SqlHelper(1)
print id(obj2) #37195368

这样创建实例SqlHelper(1),但生成的id不同,占用大量内存。

2、采用单实例模式

class SqlHelper:

    __static_instance = None  
    def __init__(self):
        self.hostname = ‘0.0.0.0‘
        self.port = 3306
        self.user = ‘root‘

    @classmethod
    def instance(cls):
        #cls = SqlHelper
        if cls.__static_instance:
            return cls.__static_instance
        else:
            cls.__static_instance = SqlHelper()
            return cls.__static_instance
obj1 = SqlHelper.instance()
print id(obj1) #38833768
obj2 = SqlHelper.instance()
print id(obj2) #38833768

1、创建静态字段__static_instance = None 保存永远存在内存的实例

2、调用类方法@classmethod,返回那个对象

3、通过类对象获取永远存在内存的实例

这就是创建单例模式的要点。。。。。

参考来源:

http://www.cnblogs.com/wupeiqi/

以及老男孩python开发视频

时间: 2024-10-10 09:03:53

python学习------------异常以及反射的相关文章

python学习笔记-Day08--(反射)

从一开始学习这一块感觉blog就比较难写,本来就不太会写博客的问题就更严重了. 想不出什么形象的比喻.所以要写blog的时候我的心情是这样的,但是我的心情应该调整成这样的. 还是用上课时举的例子来说明白. 首先说明一下,反射要用到内置函数, getattr(obj,name)hasattr(obj,name)delattr(obj,name)  #操作内存,不影响文件,很少使用setattr(obj,name)  #操作内存,不影响文件,很少使用 先看一下getattr()方法的说明 getat

Python学习心得(六) 反射机制、装饰器

1.反射机制 #/usr/bin/env python # -*- coding:utf-8 -*- ''' Python反射机制的核心本质:利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动 通俗讲就是通过用户传入url的不同,调用不同的模块函数,好多比较流行的web框架都是通过反射的机制,根据url的不同指向不同的模块 getattr(),hasattr(),setattr(),delattr()对模块的修改都在内存中进行,并不会影响文件中的真实内容

Python 学习之路 - 反射,hashlib

反射 1 import os 2 mo = "common" 3 # path = os.path.dirname(os.path.abspath(__file__)) 4 mod = __import__("other."+ mo,fromlist=True)#反射的方式导入一个模块,other.是模块的目录,mo是模块 5 6 7 # setattr() 在某个模块设置某个功能 8 # delattr() 在某个模块删除某个功能 9 10 def fun():

Python学习系列之反射

反射的定义 根据字符串的形式去某个对象中操作成员 根据字符串的形式去某个对象中寻找成员 根据字符串的形式去某个对象中设置成员 根据字符串的形式去某个对象中删除成员 根据字符串的形式去某个对象中判断成员是否存在 反射相关函数 getattr(object,name,[default]) 根据字符串的形式去某个对象中寻找成员 自定义一个模块(用来测试寻找这个模块里的某个成员) # 自定义模块的内容 [[email protected] ~]# cat commons.py #!/usr/bin/en

python学习 异常

#===========================常见异常 ===================== #print(a);#NameError: name 'a' is not defined 变量未定义 #if True:#SyntaxError: unexpected EOF while parsing 语法错误 #f=open("123.txt");#FileNotFoundError: [Errno 2] No such file or directory: '123.

python学习之类的反射(2018.6.18)

在学习网络编程的时候用到反射,然后发现自己反射这部分的应用不是很熟练,决定返回来重新整理一下 对于类的反射,主要有四个用法,下面都说一下 1.hasattr 判断对象或者类是否存在指定的属性,看代码以及结果 class people: def __init__(self,name,age): self.name = name self.age = age def talk(self): print("%s is talking."%self.name) p1 = people('ale

Python学习—异常

一.异常处理的定义 python解释器检测到错误,触发异常(也允许程序员自己触发异常) 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关) 如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理 二.异常处理的用法 为了保证程序的健壮性与容错性,即在遇到错误时候程序不会崩溃,我们需要对异常进行处理,1,如果错误发生的条件是可预知的,我们需要用if进行处理,在错误发生之前进行预防 age1 = 10 while True: age

python学习笔记__反射

反射 # 通过字符串的形式对对象中的成员进行操作(获取/查找/添加/删除). 操作的内置函数: 1.获取   getattr(object, name) # 去对象object中获取name的内容 class Foo: def __init__(self, name, age): self.name = name self.age = age obj = Foo('Lemon147', 18) v = getattr(obj, 'name') print(v) >>> Lemon147

【python学习】8.异常

[python学习]8.异常 raise Exception: 抛出指定异常 try/except: 捕捉异常 except: 第一个参数是需要捕获的异常类型,可以是多个类型组成元组,第二个参数是捕获到的异常对象, raise: 抛出已经捕获的异常 else: 当没有捕获的异常时候执行 finally: 总会被执行 def test(): try: raise Exception("test") except (Exception), e: print "Exception&