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
posted @ 2016-07-02 11:45  摸个鱼儿  阅读(239)  评论(0编辑  收藏  举报