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 ") f.write("123 ") f.write("123 ") f.write("123 ") f.write("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 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