首页 > 代码库 > 爱根,征服我的一天[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,定制自己的数据类型