Day08 面向对象 捕获异常
面向对象,异常捕获
类的成员、成员修饰符、类的特殊成员。
一、类的成员
类的成员分为三类:字段、方法和属性。
1.字段
字段可以分为普通字段和静态字段,其中普通字段属于对象,静态字段则属于类。
class Foo:
aa = 123
def xx(self):
bb = '456'
print(bb)
aa就是静态字段,bb就是普通字段。静态字段在内存只保存一份,普通字段在每个实例化对象中保存,因此如果每个对象要有相同普通字段,应该使用静态字段
2.方法
方法可以分为三种,普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
- 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
- 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
- 静态方法:由类调用;无默认参数
class Foo:
aa = 123
def xx(self):
bb = '456'
print(bb)
@staticmethod
def yy():
print("OK")
@classmethod
def zz(cls):
print(cls)
实例化对象
obj = Foo()
普通方法调用
obj.xx()
静态方法调用
Foo.yy(789)
类方法调用
Foo.zz()
3.属性
属性是类方法的变种
- 属性的定义和使用
在定义方法上面加@property
装饰器,有一个self
参数,调用的时候不用加()
class Foo:
aa = 123
def xx(self):
bb = '456'
print(bb)
@property
def rr(self):
print('属性')
属性的形式,定义时用方法的形式定义,调用时用字段的形式调用。
属性还有另外一种定义方式,即在类中定义值为property对象的静态字段
上例中我们可以改写:
class Foo:
aa = 123
def xx(self):
bb = '456'
print(bb)
def rr(self):
print('属性')
rr_other = property(rr)
Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。对于装饰器方式定义的属性,有三种更为灵活丰富的使用方式,即获取,修改,删除
class Foo():
@property
def rr(self):
print("@property")
@rr.setter
def rr(self, name):
print("rr.setter")
@rr.deleter
def rr(self):
print("rr.deleter")
q = Foo()
q.rr
q.rr = 'alex'
del q.rr
如果使用定义property静态字段的方式改写,则:
class Foo():
def f1(self):
return 'a'
def f2(self, args):
print(args)
def f3(self):
print('c')
foo = property(f1, f2, f3, 'something')
p = Foo()
res = p.foo 自动调用第一个参数的方法
print(res)
p.foo = 'alex' 自动调用第二个参数的方法,并将'alex'传入
del p.foo 自动调用第三个参数的方法
p.foo.doc 自动获取第四个参数的值
二、成员修饰符
对于类的成员都有两种形式:公有,私有。
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。
对于字段:
class Foo:
__cc = 123
def __init__(self, name):
self.__name = name
def f1(self):
print(Foo.__cc)
def f2(self):
print(self.__name)
obj = Foo('alex')
#从内部调用失败
#print(Foo.__cc)
#print(obj.__name)
#从外部调用成功
obj.f1()
obj.f2()
对于方法:
class Foo:
@staticmethod
def __f1():
print("alex")
@classmethod
def __f2(cls):
print(cls)
def f3(self):
Foo.__f1()
def f4(self):
Foo.__f2()
obj = Foo()
#从外部调用失败
# Foo.__f1()
# Foo.__f2()
#从内部调用成功
obj.f3()
obj.f4()
属性的定义与使用方式同上类似
三、类的特殊成员
Python的类成员存在着一些具有特殊含义的成员,如下:
1.__doc__
表示类的描述信息
class Foo:
""" 描述类信息 """
def func(self):
pass
print Foo.__doc__
#输出:类的描述信息
2.__module__
和__class__
__module__
表示当前操作的对象在那个模块
__class__
表示当前操作的对象的类是什么
class Foo:
def __init__(self):
self.name = 'alex'
from lib.aa import Foo
obj = Foo()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.Foo,即:输出类
3.__init__
构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
5.__call__
对象后面加括号,触发执行。
6.__dict__
类或对象中的所有成员。
7.__str__
如果一个类中定义了该方法,那么在打印对象时,默认输出该方法的返回值。
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __call__(self):
print(self.name)
print(self.age)
def __str__(self):
return '%s - %d' % (self.name, self.age)
obj = Foo('alex', 20)
Foo('eric', 30)()
obj()
print(obj)
ret = str(obj)
print(ret)
#打印对象中封装的数据
ret = obj.__dict__
print(ret)
8.__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo:
def __getitem__(self, item):
print('item')
print('getitem')
print(item.start)
print(item.stop)
print(item.step)
def __setitem__(self, key, value):
print('setitem')
print(key.start)
print(key.stop)
print(key.step)
def __delitem__(self, key):
print('delitem')
print(key.start)
print(key.stop)
print(key.step)
def __iter__(self):
yield 1
yield 2
obj = Foo()
ret = obj[1:2]
obj[1:3] = [11, 22, 33, 44,]
del obj[1:2]
9.__iter__
用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了__iter__
class Foo(object):
def __init__(self, sq):
self.sq = sq
def __iter__(self):
return iter(self.sq)
obj = Foo([11,22,33,44])
for i in obj:
print i
10.__getslice__、__setslice__、__delslice__
该三个方法用于分片操作,如:列表
class Foo(object):
def __getslice__(self, i, j):
print '__getslice__',i,j
def __setslice__(self, i, j, sequence):
print '__setslice__',i,j
def __delslice__(self, i, j):
print '__delslice__',i,j
obj = Foo()
obj[-1:1] # 自动触发执行 __getslice__
obj[0:1] = [11,22,33,44] # 自动触发执行 __setslice__
del obj[0:2] # 自动触发执行 __delslice__
其他:
class C1:
def f1(self):
print('c1.f1')
class C2(C1):
def f2(self):
# super 关键字, 主动执行父类方法
super(C2, self).f1()
print('c2.f2')
obj = C2()
obj.f2()
异常捕获
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户
try:
pass
except Exception as ex:
pass
1.异常种类
python中的异常种类非常多,每个异常专门用于处理某一项异常
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确
s1 = 'hello'
try:
int(s1)
except KeyError as e:
print '键错误'
except IndexError as e:
print '索引错误'
#万能异常放在最后
except Exception as e:
print '错误'
2.异常结构
try:
# 主代码块
pass
except KeyError as e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块
pass
3.主动触发异常
try:
raise Exception('错误了。。。')
except Exception as e:
print e
4.自定义异常
class defined(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
raise defined('我的异常')
except defined as e:
print e
5.断言
assert语句用来声明某个条件是真的,当assert语句失败的时候,会引发一AssertionError。
# assert 条件
assert 1 == 1
assert 1 == 2