目录
面向对象进阶
一、issubclass 和 isinstance
1.1 issubclass
issubclass()
作用:用来判断括号内的第一个类是不是第二个类的子类,返回结果为True或False。
例如:
class A:
pass
class B(A):
pass
class C:
pass
print(issubclass(B,A)) # True
print(issubclass(C,A)) # False
1.2 isinstance
isinstance()
作用:用来判断括号内第一个参数是不是第二个参数的对象,返回结果为True或False。
例如:
class A:
pass
class B:
pass
a = A()
print(isinstance(a,A)) # True
print(isinstance(a,B)) # False
二、反射
2.1 什么是反射
通过字符串来判断、获取、设置、删除对象(包括类、模块等,一切皆对象)中的属性或方法。
2.2 四个可以通过字符串操作对象属性和方法的内置函数
四个函数括号里的第一个参数都是对象
hasattr(): 判断一个属性是否在对象中,返回True或者False
getattr(): 通过字符串获取属性或方法,如果获取到了,就会返回相应的属性或方法
setattr(): 通过字符串来设置属性或方法
delattr(): 通过字符串来删除属性或方法
2.2.1 hasattr()
判断一个属性是否在对象中,第一个参数是对象,第二个参数是属性,返回True或False
class Foo:
def run(self):
print('run')
def speak(self):
print('speak')
p=Foo()
cmd=input('请输入命令:')
if hasattr(p,cmd): # 先判断属性cmd是否在对象p中
run=getattr(p,cmd) # 如果输入run,该属性或方法就在对象p中,就会返回,加括号就可以调用
run()
else:
print('该命令不存在') # 输入的属性不在对象中的话,就执行这步
2.2.2 getattr()
通过字符串获取属性或方法,如果获取到了,就会返回相应的属性或方法,用法在上面的代码里已经写了
2.2.3 setattr()
1、通过用户输入key和value往对象中赋值
class Foo:
def run(self):
print('run')
def speak(self):
print('speak')
p=Foo()
key=input('请输入key:') # 输入age
value=input('输入value:') # 输入18
setattr(p,key,value) # 将{'ag':'18'}赋值给对象p
print(p.age) # 18
2、动态的往对象中放方法
class Foo:
def run(self):
print('run')
def speak(self):
print('speak')
p=Foo()
def test(a):
print(a)
print(p.__dict__) # {}
setattr(p,'test',test)
print(p.__dict__) # {'test': <function test at 0x000001DF69C81E18>}
p.test(0) # 0
2.3.4 delattr()
动态删除对象p中属性为变量a的属性
class Foo:
def run(self):
print('run')
def speak(self):
print('speak')
p=Foo()
p.name='lqz'
p.age=18
p.sex='male'
a=input('请输入要删除的属性:') # 输入sex
print(p.__dict__) # {'name': 'lqz', 'age': 18, 'sex': 'male'}
delattr(p,a) #把属性sex删除
print(p.__dict__) # {'name': 'lqz', 'age': 18}
# 直接p.a是不对的
# del p.a 这个会报错
三、内置方法
之前学过__init__
3.1 __str__
和__repr__
1、__str__
:如果不重写__str__
,print打印会打印出内存地址,如果重写了,会打印出你想要的
2、__repr__
:和__str__
类似,在交互式命令下直接写变量名,会执行__repr__
class Foo:
def __init__(self,name):
self.name=name
def __str__(self):
return '['+self.name+']'
f=Foo('nick')
print(f.__str__()) # [nick]
print(f) #相当于上面那句 # [nick]
l=[1,2,3]
#本质也是已经调用list的__str__方法
print(l)
3.2 点拦截方法:__setattr__
,__delattr__
,__getattr__
如果去对象中获取属性,一旦取不到,会进入到__getattr__
如果去对象中赋值属性,一旦取不到,会进入到__setattr__
如果删除对象中的属性,会进入__delattr__
class Foo:
def __init__(self,name):
self.name=name
def __getattr__(self, item):
# print('xxxx')
return '你傻逼啊,没有这个字段'
def __setattr__(self, key, value):
print('yyyyy')
def __delattr__(self, item):
print('zzzzz')
f=Foo('nick') # 给对象f赋值属性,对象中没有这个属性,进入到__setattr__方法 # yyyyy
print(f.name) # 获取name属性,对象中没有属性,进入__getattr__方法 # 你傻逼啊,没有这个字段
print(f.age) # 没有age属性,进入__getattr__方法 # 你傻逼啊,没有这个字段
print(f.__dict__) # {}
print(f.name) # 没有name属性,进入__getattr__方法 # 你傻逼啊,没有这个字段
f.sex='male' # 给对象f赋值属性,对象中没有sex这个属性,进入到__setattr__方法 # yyyyy
del f.name # 删除对象name属性,对象中没有这个属性,进入__delattr__方法 # zzzzz
print(f.__dict__) # {}
3.3 __item__
对象通过[] 中括号取值、赋值、删除值得时候会调用__item__
方法
class Foo:
def __init__(self, name):
self.name = name
def __getitem__(self, item):
name=getattr(self,item)
# print(name)
# print(self.__dict__[item])
return name
# return self.__dict__[item]
def __setitem__(self, key, value):
print('obj[key]=lqz赋值时,执行我')
self.__dict__[key] = value
def __delitem__(self, key):
print('del obj[key]时,执行我')
self.__dict__.pop(key)
f=Foo('nick')
print(f['name'])
3.4 __call__
对象加括号会调用它
class Foo:
def __call__(self):
print('xxxx')
f=Foo()
f() # xxxx
3.5 __enter__
和__exit__
with管理上下文的本质
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
with Open('a.txt') as f:
print('=====>执行代码块')
# print(f,f.name)
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
- exit()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
try:
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
except Exception as e:
print(e)
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
<class 'AttributeError'>
着火啦,救火啊
<traceback object at 0x1065f1f88>
着火啦,救火啊
- 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
return True
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
print('0' * 100) #------------------------------->会执行
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
<class 'AttributeError'>
着火啦,救火啊
<traceback object at 0x1062ab048>
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000