Python之路【第六篇】:面向对象编程相关
判断类与对象关系
isinstance(obj, cls)
判断对象obj是否是由cls类创建的
#!/usr/bin/env python #-*- coding:utf-8 -*- class Foo(object): pass obj = Foo() print isinstance(obj, Foo) #输出结果:True #如果对象obj是由Foo类创建的,那么就会返回True 否则返回False #!/usr/bin/env python #-*- coding:utf-8 -*- class Foo(object): pass class Boo(object): pass obj = Boo() print isinstance(obj,Foo) #输出结果:False
issubclass(Boo, Foo)
检查Boo类是否是 Foo类的派生类
#!/usr/bin/env python #-*- coding:utf-8 -*- class Foo(object): pass class Boo(Foo): pass print issubclass(Boo,Foo) #同理如果Boo,是Foo的派生类那么返回True
异常处理
一、异常处理的作用
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!(这里的大黄页通常是写代码是用户访问网页,如果出现错误之后返回的一个黄色的报错页面通常称为:大黄页)
例子:
拿咱们刚开始学的时候遇到的问题来举例:
#!/usr/bin/env python #-*- coding:utf-8 -*- str_input = 'tianshuai' number = int(str_input) print number 报错信息: ''' Traceback (most recent call last): File "C:/Github/homework/tianshuai/boke.py", line 5, in <module> number = int(str_input) ValueError: invalid literal for int() with base 10: 'tianshuai' '''
上面的信息是不是非常的不友好!
用异常处理来做:
try: str_input = 'tianshuai' number = int(str_input) print number except Exception,e: print "\033[32;1m出现错误如下\033[0m" print e #输出结果: ''' 出现错误如下 invalid literal for int() with base 10: 'tianshuai' '''
二、异常处理基础
拿下面的代码来说:
假如我有一个程序,获取用户输入的数字!这里我不能控制用户输入什么。
看下面输入了一个字符串,这里我可不可以用异常处理来告诉用户,你的输入字符串啊!
user_input = raw_input("\033[32;1m请输入数字:\033[0m") number = int(user_input) #请输入数字:sdlkf ''' Traceback (most recent call last): File "E:/ѧϰ/GitHub/homework/tianshuai/master.py", line 5, in <module> number = int(user_input) ValueError: invalid literal for int() with base 10: 'sdlkf' '''
假如我使用异常处理:
try: #正常逻辑代码 user_input = raw_input("\033[32;1m请输入数字:\033[0m") number = int(user_input) except Exception,e: #这个e是对象Exception类创建的!Exception这里面封装了你上面逻辑块出现问题的所有错误 #逻辑代码出现错误,这里的代码块就是如果上面的代码出现问题之后执行这个代码块的内容 print e #如果这个e你不想要,可以自己定义 #这里也可以记录日志,把错误的详细记录,错误详细在e里了! #结果: ''' 请输入数字:sdfs invalid literal for int() with base 10: 'sdfs' '''
三、异常处理种类
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
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
更多异常
#!/usr/bin/env python #-*- coding:utf-8 -*- #例子1 list = ["wupeiqi", 'alex','luotianshuai'] try: list[10] except IndexError, e: print e #异常处理提示:list index out of range #例子2 dic = {'k1':'v1'} try: dic['k20'] except KeyError, e: print e #异常处理提示:'k20' #例子3 s1 = 'hello' try: int(s1) except ValueError, e: print e #异常处理提示:invalid literal for int() with base 10: 'hello'
对于上面的,异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。如果是int('qew'),你用的是IndexError
异常不是他的异常处理,就会直接报错
# 未捕获到异常,程序直接报错 s1 = 'hello' try: int(s1) except IndexError,e: print e ''' 报错结果: Traceback (most recent call last): File "E:/ѧϰ/GitHub/homework/tianshuai/master.py", line 8, in <module> int(s1) ValueError: invalid literal for int() with base 10: 'hello' '''
写程序的时候需要考虑所有可能出现的异常,可以这么写:
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前面进行单独的处理!比如日志、提醒等!
s1 = 'hello' try: int(s1) except KeyError,e: print '键错误' except IndexError,e: print '索引错误' except Exception, e: print '错误'
四、主动触发异常
比如我现在有一个连接数据库的模块,如果无法连接数据库的时候,这个会影响我剩下所有代码的进行,这时我需要主动去触发一个异常!
mysql_contrl.py
#!/usr/bin/env python #-*- coding:utf-8 -*- def connect(): return False #无法连接数据库报错(假设无法连接数据库返回False)
主代码
#!/usr/bin/env python #-*- coding:utf-8 -*- import model if __name__ == '__main__': try: result = model.connect() if result: print "\033[32;1m连接成功\033[0m" else: raise Exception('\033[31;1m无法连接数据库\033[0m')#无法连接的时候主动触发一个异常,这个异常的明细,是我自己来指定的 except Exception,e: print e
五、异常其他结构
#!/usr/bin/env python #-*- coding:utf-8 -*- try: #这一块才是最主要的逻辑处理块,所有的逻辑处理都是放在这里的 pass except KeyError,e:#如果出现KeyError错误,首先被他捕获,下面的except就不执行了 pass except Exception,e:#如果上面的错误没有找到就去,万能异常里找 pass else:#这里什么时候执行呢,逻辑代码里为出现异常这个代码快才执行 pass finally: #不管上面是否出现异常,最后执行完之后,这里永远执行!finally什么时候用?你上面执行一个操作,连接数据库,我这里就可以执行,断开数据库释放资源!(举例) pass ''' 上面的代码就是全部的异常处理的内容 '''
六、自定义异常
咱们看下异常处理的代码!咱们这里知道e是一个对象,这个e是由Exception类创建的,咱们print这个e是一个字符串,那么这个字符串是怎么来的呢?
#!/usr/bin/env python #-*- coding:utf-8 -*- try: int('sdfsdfs') except Exception,e: print e #执行结果: ''' invalid literal for int() with base 10: 'sdfsdfs' '''
在看这个代码
class A(object): pass obj = A() print obj #执行结果: ''' <__main__.A object at 0x0000000000AA2A20> '''
嗯?这是为什么呢?这个咱们应该知道的,在学面向对象的时候类有一个__str__方法
__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
#!/usr/bin/env python #-*- coding:utf-8 -*- class A(object): pass def __str__(self): return "shuaige is so handsome" obj = A() print obj #执行结果: ''' shuaige is so handsome '''
OK既然我们知道异常的原理了,当我们print “e”的时候是调用的__str__方法我们也就可以自己写一个异常了!
#!/usr/bin/env python #-*- coding:utf-8 -*- class Shuaigeerror(Exception):#自己定义一个异常并继承Exception,除了自己定义的异常Exception的万能异常也可以使用 def __init__(self,msg=None): self.msg = msg def __str__(self): if self.msg: return self.msg #定义了错误了信息提示的错误 else: return 'something error' #默认如果不传参数的时候提示的错误 try: raise Shuaigeerror('shuaige is handsome') except Exception,e: print e #输出结果 ''' shuaige is handsome '''
七、断言
assert 1 == 1 #如果条件满足就不报错,如果条件不满足就会报错 assert 1 == 2 ''' 这个和 raise Exception('string') 只要你定义了raise肯定会报错 这个一般什么时候使用,比如我写了一个软件,上面有些条款: 你必须接受,你不接受我就不让你用! '''
反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
首先看下对象的操作:
class Foo(object): def __init__(self): self.name = 'wupeiqi' 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')
python中一切实物都是对象,类、模块也是对象!反射是通过字符串的形式操作对象相关的成员!
实例:
我有两个web模块:web1,web2,里面包含了所有用户的跳转页面!web1包含了所有用户的登录跳转 web2里包含了所有用户的认证跳转
模块代码:
#web1 #!/usr/bin/env python #-*- coding:utf-8 -*- def login1(): return 'web1.login' #web2 #!/usr/bin/env python #-*- coding:utf-8 -*- def authentication(): return 'web2.authentication'
主代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- models,action = raw_input("请输入URL:").split('/') model = __import__(models) ''' 咱们在导入模块的时候:import web1 这里的web1咱们不知道他是什么数据类型,他不是一个基本的数据类型 这里这个__import__(’web1‘)是以字符串的方式导入模块 ''' model_name = getattr(model,action) ret = model_name() print ret #输出结果: ''' 请输入URL:web1/login1 web1.login '''
咱们上面的代码是是用反射来实现的,想想一下如果用if..else来实现这个功能,如果我这个web1里有N种方法呢?或者我有N个模块呢?
如果用反射实现动态的导入模块和方法是不是就非常简单了?
有兴趣的可以实验一下用if..else来实现上面代码的功能对下!
在文件中的反射:
import sys def function(): print "hello world" current_model = sys.modules[__name__] if hasattr(current_model,'function'): renamefunc = getattr(current_model,'function') renamefunc() print sys.modules #一字典的形式显示当前脚本中的模块 print __name__ # __name__ = __main__ 指定当前文件 print sys.modules[__name__] # <module '__main__' from 'C:/Github/homework/test/fanshe.py'> 当前文件
更多请看:http://www.cnblogs.com/wupeiqi/articles/5017742.html