python之反射
isinstance(obj,cls)检查obj是否是类的对象
class Foo(object):
pass
obj=Foo()
print(isinstance(obj,Foo))
>>
True
Issubclass(sub,super)检查sub类是否是super类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
print(issubclass(Bar,Foo))
>>
True
反射的概念:指程序可以访问、检测和修改它本身2状态或行为的一种能力(自省)。
Python面向对象中的反射:通过字符串的形式操作对象相关的属性。Python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
方法适用于类和对象(一切皆对象,类本身也是一个对象)
hasattr 判断object中有没有一个name字符串对应的方法或属性
hasattr(object,name)查看对象的__dict__是否有这个值,返回bool值
检测是否含有某属性
格式:print(hasattr(x,y))
class People:
country="China"
def __init__(self,name):
self.name=name
def walk(self):
print("%s is walking"%self.name)
p=People("karina")
print(hasattr(p,"name"))
>>
True
gatattr 获取属性
格式:res=getattr(x,y)
print(res)
lass People:
country="China"
def __init__(self,name):
self.name=name
def walk(self):
print("%s is walking"%self.name)
p=People("karina")
print(getattr(p,"name"))
>>
karina


setattr 设置属性
格式:setattr(x,y,z)
print(x.__dict__)
class People:
country="China"
def __init__(self,name):
self.name=name
def walk(self):
print("%s is walking"%self.name)
p=People("karina")
setattr(p,"age",18)#setattr(x,y,z)分别传入对象,属性,值
print(p.__dict__)
print(p.age)
#p.sex="female" #设置一个性别
#print(p.sex) #打印
#print(p.__dict__)#查看对象对应字典中的信息
>>
female
{'name': 'karina', 'sex': 'female'}#字典中已经添加性别这个键值对
delattr 删除属性
格式:delattr(x,y)
Delattr(x,y1111)#不存在,则报错
Print(x.__dict__)
class People:
country="China"
def __init__(self,name):
self.name=name
def walk(self):
print("%s is walking"%self.name)
p=People("karina")
delattr(p,"name") #删除对象的name
# print(p.name)
print(p.__dict__)#查看对象对应的字典信息
>>
{}
使用反射的好处
1. 实现可插拔机制
就是事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,其实是一种“后期绑定”,即事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
sever端调用FtpClient


2.动态导入模块(基于反射当前模块成员)
import sys #固定格式
def s1():
print("s1")
def s2():
print("s2")
this_module=sys.modules[__name__]# sys.modules[__name__]固定格式
print(hasattr(this_module,"s1"))
print(getattr(this_module,"s2"))
>>
True
<function s2 at 0x015A41E0>
导入模块的推荐使用方法
import importlib
t=importlib.import_module("time")
print(t.time())
attr系列的使用
class Foo:
def __init__(self,y):
self.name=y
def __setattr__(self, key, value):
#为对象设置属性的时候,触发运行
if not isinstance(value,str):#设置类型限制
raise TypeError("must be str")
self.__dict__[key]=value#添加到字典中
def __delattr__(self, item):
#删除属性
print("delatter:%s"%item)
self.__dict__.pop(item)#在字典中删除
def __getattr__(self, item):
#属性不存在的情况下才会触发
print("getattr-->%s %s"%(item,type(item)))
f=Foo("egon")
f.age="18"
print(f.name)#在字典中查找
print(f.age)#在字典中查找
print(f.__dict__)
del f.name#删除字典中的name属性
print(f.__dict__)
f.xx
>>
egon
18
{'name': 'egon', 'age': '18'}
delatter:name
{'age': '18'}
getattr-->xx <class 'str'>
二次加工(定义自己的数据类型)
二次加工使用继承的原理
class List(list):#继承list所有的属性
def append(self,p_object):#子类定义派生的方法
if not isinstance(p_object,int):#设置类型限制
raise TypeError
super().append(p_object)#继承父类
def insert(self, index, p_object):
if not isinstance(p_object,int):
raise TypeError
super().insert(index,p_object)
l=List([1,2])
print(l)
l.append(5)
print(l)
l.insert(0,52)
print(l)
>>
[1, 2]
[1, 2, 5]
[52, 1, 2, 5]
授权:授权是包装的一个特性,包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原产品的功能,其他的则保持原样。授权的过程中,即是所有更新的功能是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法
import time
class Open:
def __init__(self,filepath,m="r",encode="utf8"):
self.x=open(filepath,mode=m,encoding=encode)
self.filepath=filepath
self.mode=m
self.encoding=encode
def write(self,line):
print("f自己的write",line)
t=time.strftime("%Y-%m-%d %X")
self.x.write("%s %s"%(t,line))
def __getattr__(self, item):
return getattr(self.x,item)
f=Open("b.txt","w")
f.write("123\n")
f.write("123\n")
f.write("123\n")
f.write("123\n")
f.write("123\n")
>>
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
f=Open("b.txt","r+")
res=f.read()
print(res)
>>
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
2017-04-24 18:38:34 123
浙公网安备 33010602011771号