首页 > 代码库 > 爱根,征服我的一天[isinstance,issubclass]、反射、内置attr,定制自己的数据类型
爱根,征服我的一天[isinstance,issubclass]、反射、内置attr,定制自己的数据类型
今日重点:
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
isinstance,issubclass
# isinstance(obj,cls)检查是否obj是否是类 cls 的对象。 # issubclass(sub,super)检查sub类是否是 super 类的派生类。 class People: pass class List(list): pass class LIST(List): pass p=People() l=List() print(isinstance(p,People)) #True print(isinstance(l,People)) #False print(issubclass(List,list)) #True print(issubclass(People,list)) #False print(issubclass(LIST,List)) #True print(issubclass(LIST,list)) #True
反射:getattr,setattr,delattr,hasattr
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)。
#!!!!!!!!!!!!!!!!!!!!!!类也是对象!!!!!!!!!!!!!!!!!!!!!!! class People: country="china" def test(self): print("from test") p=People() print(hasattr(p,"test")) #True print(hasattr(p,"country")) #True print(hasattr(People,"test")) #True print(hasattr(People,"country")) #True print(getattr(p,"test")) #<bound method People.test of <__main__.People object at 0x000000000280D7B8>> print(getattr(p,"123","返回值default为None,可以自己定义:這是我定义的!")) #返回值default为None,可以自己定义:這是我定义的! a=getattr(People,"test","返回值default为None,可以自己定义:這是我定义的!")#拿到类的函数属性的内存地址。 a(p) #from test 调用。 setattr(p,"a123","456") #新增对象的数据属性。 print(p.__dict__) #{‘a123‘: ‘456‘} 对象的名称空间。 print(p.a123) #456 查看结果。 setattr(People,"country","China") #修改类的变量属性。 print(People.country,People.__dict__) #China 查看。 setattr(People,"abc","efg") #新增类的变量属性。 print(People.__dict__) #查看名称空间。 print(People.abc) #efg 检验。 delattr(p,"a123") #删除p名称空间下的“a123”数据属性。 print(p.__dict__) #验证,为{} delattr(People,"abc") #删除类名称空间下的“abc”数据属性。 print(People.__dict__) #验证,没有了。
反射的简单用途!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
import sys def add(): print("from add") def dell(): print("from dell") def change(): print("from change") def search(): print("from search") this_module=sys.modules[__name__] while True: choice=input("please input you choice") if not choice:continue if hasattr(this_module,choice): getattr(this_module,choice)()
#反射当前模块的属性 import sys #类也是对象 country="china" class People: pass class Animal: acountry="Africa" def walk(self): print("From Animal") def test(): print("From test!") print("-------",__name__,type(__name__)) #------- client <class ‘str‘> this_module=sys.modules[__name__] # print("*******",this_module) #******* <module ‘client‘ from ‘D:\\PycharmProjects\\py_fullstack_s4\\day31\\client.py‘> # print(hasattr(this_module,"country")) #True 判断object中有没有一个name字符串对应的方法或属性 # print(getattr(this_module,"country")) #china # print(hasattr(this_module,"People")) #True # print(hasattr(this_module,"test")) #True # print(hasattr(this_module,"acountry"))#False # print(hasattr(Animal,"acountry")) #True 判断object中有没有一个name字符串对应的方法或属性 # print(hasattr(Animal,"country")) #False # getattr(this_module,"test")() #From test! # setattr(this_module,"country","CHINA") #设置模块对象下的country数据属性。 # print(getattr(this_module,"country")) #CHINA # delattr(this_module,"country") #删除属性。 # print("country" in this_module.__dict__) #False
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
通过反射来实现插拔机制:
#ftpclient.py 端。 class FtpClient: ‘ftp客户端,但是还么有实现具体的功能‘ def __init__(self,addr): print(‘正在连接服务器[%s]‘ %addr) self.addr=addr def test(self): print(‘test‘) def get(self): print(‘get------->‘) #ftpserver.py 端。 import ftpclient #导入模块! print(ftpclient) #ftpclient是一个模块,当然,一切皆对象,可以调用该模块下的任何属性。 print(ftpclient.FtpClient) #<class ‘ftpclient.FtpClient‘>,这是调用该模块下的一个类。 obj=ftpclient.FtpClient(‘192.168.1.3‘) #实例化,过程中触发该打印:正在连接服务器[192.168.1.3] print(obj) #<ftpclient.FtpClient object at 0x0000000001E7D048> 代表该模块下的类下的对象。 obj.test() #同样,该对象可以调用他始祖模块中的函数,test。 f1=ftpclient.FtpClient(‘192.168.1.1‘) #生成实例f1。 if hasattr(f1,‘get‘): #如果该实例f1下有“get”的方法, func=getattr(f1,‘get‘) #则拿到该函数的内存地址, func() #执行。 # if not hasattr(f1,"abc"): # print("没有该方法!") #这是不存在该方法的情况,只是举个例子。 else: print(‘其他逻辑‘) #没有的话,直接打印其他逻辑。
333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
内置attr:__getattr__,__setattr__,__delattr__
class People: def __init__(self,name): self.name=name def __setattr__(self, key, value): #__setattr__添加/修改属性会触发它的执行。 if not isinstance(value,str): raise("typeError") self.__dict__[key]=value #如果这里是self.key=value,因为key,和value是字符串,self.后面不能是字符串,又者setattr(self,key,value)的话,就会递归。
#setattr(self,key,value)=self.key=value,会无限的递归。 def __delattr__(self, item): #__delattr__删除属性的时候会触发他的执行。 if not isinstance(item,str): raise("typeError") self.__dict__.pop(item) def __getattr__(self,item,): #__getattr__只有在使用.调用属性且属性不存在的时候才会触发。 print(item,type(item)) p=People("egon") p.sex="male" print(p.__dict__) print(p.sex) print(p.name) print(p.xxxx) #xxxx <class ‘str‘> #只有通过修改字典才能完成对对象属性的修改操作,所以只有是修改self.__dict__
444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
定制自己的数据类型:
1.继承的方式:继承父类的方法,更改性能后来实现自己的功能。
class List(list): #继承list类的功能。 def append(self, object): if not isinstance(object,int): #改变append数据类型的判断机制,必须是int。 raise("must be int") #self.append(object) #这样会发生递归。 super().append(object) #继承父类list的功能。 @property def mid(self): #新增查看中间值的功能。 return self[int(len(self)/2)] a = List([1, 2, 3]) a.append(6) print(a) print(a.mid) a.pop(1) #其他未定义的属性还是继承父类的方法。 print(a) a.insert(0,9) print(a)
2.授权的方式
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法
import time class Open: def __init__(self,filepath,m=‘r‘,encode=‘utf-8‘): 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) #这项是保证除了write外其他方法可以调用。其实是从句柄中找句柄的方法,作为返回值。 f=Open(‘b.txt‘,‘w‘) print(f)
爱根,征服我的一天[isinstance,issubclass]、反射、内置attr,定制自己的数据类型