面向对象高级
isinstance(obj,cls)
检查obj是否是类 cls 的对象
|
1
2
3
4
5
6
7
8
|
class
Foo(
object
):
pass
obj
=
Foo()
print
(
isinstance
(obj, Foo))
输出:
True
|
issubclass(sub,super)
检查sub类是否是 super 类的派生类
|
1
2
3
4
5
6
7
|
class
Foo(
object
):
pass
class
Bar(Foo):
pass
print
(
issubclass
(Bar, Foo))
|
b.反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)
python面向对象中的反射:通过字符串反射到真实的属性上
面向对象中类中属性的两种调用方法:
1. 类名.属性
2.类名.__dict__[‘属性名’] #通过字符串的形式
|
1
2
3
4
5
6
7
8
9
10
|
class
Foo:
x
=
1
def
__init__(
self
,name):
self
.name
=
name
def
f1(
self
):
print
(
'from f1'
)
print
(Foo.x)
#方法1Foo.__dict__['x'] #方法2
|
实现自省的函数,通过操作字符串的方式映射到属性(适用于类和对象,在python中一切皆对象,类本身也是一个对象)
hasattr(obj,’name’) 判断obj中有没有一个name字符串对应的方法或属性
setattr(x,’y’,’v’) 设置函数,x对象名,y属性,v值
getattr(x,’y’) 取值函数,x对象名,y属性
delattr(x,’y’) 删除函数,x对象名,y属性
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
Ftpserver:
def
__init__(
self
,host,port):
self
.host
=
host
self
.port
=
port
def
run(
self
):
while
True
:
cmd
=
input
(
'>>: '
).strip()
if
not
cmd:
continue
# 判断输入是否为空
if
hasattr
(
self
,cmd):
# 判断类中是否存在此方法
func
=
getattr
(
self
,cmd)
# 取出该方法的值并赋值给func
func()
def
get(
self
):
print
(
'get func'
)
def
put(
self
):
print
(
'put func'
)
|
反射的好处:
1.实现可插拔机制:
可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能(首先使用hasattr进行判断是否存在此方法,存在则执行,不存在则跳过)
2.动态导入模块(基于反射当前模块成员)
c.item系列
__setitem__ 设置函数
__getitem__ 取值函数
__delitem__ 删除函数
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class
Foo:
def
__getitem__(
self
, item):
print
(
'=====>get'
)
return
self
.__dict__[item]
def
__setitem__(
self
, key, value):
print
(
'==============>set'
)
self
.__dict__[key]
=
value
# setattr(self,key,value)
def
__delitem__(
self
, key):
print
(
'============>del'
)
self
.__dict__.pop(key)
f
=
Foo()
f[
'x'
]
=
123123123123
# 通过f[]的方式对对象进行操作时会调用item方法
print
(f[
'x'
])
del
f[
'x'
]
输出:
=
=
=
=
=
=
=
=
=
=
=
=
=
=
>
set
=
=
=
=
=
>get
123123123123
=
=
=
=
=
=
=
=
=
=
=
=
>
del
|
d.打印对象信息__str__
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
People:
def
__init__(
self
,name,age,sex):
self
.name
=
name
self
.age
=
age
self
.sex
=
sex
def
__str__(
self
):
#在对象被打印时触发执行
return
'<name:%s age:%s sex:%s>'
%
(
self
.name,
self
.age,
self
.sex)
p1
=
People(
'egon'
,
18
,
'male'
)
p2
=
People(
'alex'
,
38
,
'male'
)
print
(p1)
print
(p2)
|
e.析构方法__del__
当对象在内存中被释放时,自动触发执行
注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__
典型的应用场景:
创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中,当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class
Foo:
def
__init__(
self
,x):
self
.x
=
x
def
__del__(
self
):
#在对象资源被释放时触发
print
(
'-----del------'
)
print
(
self
)
f
=
Foo(
100000
)
del
f
print
(
'=======================>'
)
# 析构方法__del__与文件处理原理差不多:
f
=
open
(
'a.txt'
)
#做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
del
f
#只回收用户空间的f,操作系统的文件还处于打开状态
#所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
f
=
open
(
'a.txt'
)
f.close()
# f.close就相当于析构方法__del__,在回收用户空间的同时回收系统空间
|
7、异常处理
异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止)
错误有两种:
a.语法错误(在语法检测阶段抛出,必须在程序执行前就改正)
b.逻辑错误
例如:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
TypeError
# 类型错误
for
i
in
3
:
pass
NameError
# 名称错误
aaaaa
ValueError
# 值错误
int
(
'asdfsadf'
)
IndexError
# 索引错误
l
=
[
1
,
2
]
l[
1000
]
KeyError
# key错误
d
=
{
'a'
:
1
}
d[
'b'
]
AttributeError
# 属性错误
class
Foo:
pass
Foo.x
|
常见异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python 代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
异常处理
a. 如果错误发生的条件是可预知的,我们需要用if进行处理:在错误发生之前进行预防
|
1
2
3
4
5
6
7
8
|
AGE
=
10
while
True
:
age
=
input
(
'>>: '
).strip()
if
age.isdigit():
#只有在age为字符串形式的整数时,下列代码才不会出错,该条件是可预知的
age
=
int
(age)
if
age
=
=
AGE:
print
(
'you got it'
)
break
|
b. 如果错误发生的条件是不可预知的,则需要用到try...except:在错误发生之后进行处理
异常类只能用来处理指定的异常情况,如果非指定异常则无法处理
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
try
:
aaaa
# 抛出NameError异常
print
(
'==-==>1'
)
l
=
[]
l[
3
]
# 抛出IndexError异常
print
(
'==-==>2'
)
d
=
{}
d[
'x'
]
# 抛出KeyError异常
print
(
'==-==>3'
)
# 多分支异常
except
NameError as e:
print
(e)
except
IndexError as e:
print
(e)
except
KeyError as e:
print
(e)
except
Exception as e:
# 万能异常,能捕捉到所有的异常
print
(e)
else
:
print
(
'在没有错误的时候执行'
)
finally
:
print
(
'无论有无错误,都会执行'
)
|
c.主动抛出异常
|
1
2
3
4
|
try
:
raise
TypeError(
'类型错误'
)
except
Exception as e:
print
(e)
|
d.自定义异常
|
1
2
3
4
5
6
7
|
class
EgonException(BaseException):
def
__init__(
self
,msg):
self
.msg
=
msg
def
__str__(
self
):
return
'<%s>'
%
self
.msg
raise
EgonException(
'egon 的异常'
)
|
e.断言
assert
本文转自lyndon博客51CTO博客,原文链接http://blog.51cto.com/lyndon/1961399如需转载请自行联系原作者
迟到的栋子