反射,元类
内置函数
# class Foo: # pass # obj=Foo # print(isinstance(obj,Foo)) #在python3中统一类与类型的概念 #d={"x":1}#d=dict({"x":1}) #print(type(d) is dict) # print(isinstance(d,dict)) isinstance(对象名,类名) 判断是否是实列 # issubclass(子类,父类) 判断一个类是不是另一个类的子类 # class Parent: # pass # class Sub(Parent): # pass # print(issubclass(Sub,Parent)) # print(issubclass(Parent,object))
反射
1、什么是反射
通过字符串来操作类或者对象的属性
2、如何用
hasattr
getattr
setattr
delattr
class People: country="China" def __init__(self,name): self.name=name def eat(self): print("%s is eating" %self.name) peo1=People("egon") print(hasattr(peo1,"eat"))#查看peo1有没有eat属性 #属性需要加引号,底层原理就是依次判断从对象空间->子类->父类里面是否存在eat print(getattr(peo1,"eat"))#在又的情况下,用get拿出peo1中的eat,相当于打印peo1.get print(getattr(peo1,"XXXX","None"))#在找不到这个属性的时候返回None setattr(peo1,"age",18)#peo1.age=18 #修改属性 print(peo1.age) print(peo1.__dict__) delattr(peo1,"name")#del peo1.name #删除属性 print(peo1.__dict__)
class Ftp: def __init__(self,ip,port): self.ip=ip self.port=port def get(self): print("GET function") def put(self): print("PUT function") def run(self): while True: choice = input(">>:").strip() # print(choice,type(choice)) # if hasattr(self,choice):#self是对象conn,#先判断输入的内容是否存在 # method=getattr(self,choice)#存在就获取相应功能 # method()#调用 # else: # print("输入的命令不存在") method = getattr(self,choice,None) if method is None: print("输入的命令不存在") else: method() conn=Ftp("1.1.1",23) conn.run()
# __str__方法 # class Foo: # pass # obj=Foo()#与d={"x":1}一样 # print(obj)#与print(d)一样,只是obj打印出来是内存地址,d是肉眼能看见的内容 # class People: # def __init__(self,name,age): # self.name=name # self.age=age # #在对象self被打印时,自动触发,应该是打印该方法内采集与对象相关的信息,然后拼接成字符串返回 # def __str__(self): # return"<name:%s age:%s>" %(self.name,self.age) #必须返回的是字符串 # # obj = People("egon",18) # obj1=People("yf",17) # print(obj)#打印对象时触发__str__ # print(obj1)
#__def__格式分析构建方法 #会在对象被删除之前自动触发,文件关闭操作系统可以用到 class People: def __init__(self,name,age): self.name=name self.age=age # self.f=open("a.txt","wt",encoding="utf-8") def __del__(self):#程序结束之前自动回收操作系统资源,即文件使用时候用 print("is")#显示运行标记 # self.f.close() #达到程序运行结束前回收操作系统资源 obj=People("yf",17) print(obj) del obj print("ting")
1、什么是元类
在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象
负责产生该对象的类称之为元类,即元类可以简称为类的类
class Foo: # Foo=元类() 调用类的类是元类
pass
2、为何要用元类
元类是负责产生类的,所以我们学习元类或者自定义元类的目的
是为了控制类的产生过程,还可以控制对象的产生过程
3、如何用元类
#1、储备知识:内置函数exec的用法 #全局的名称空间 出了内置的名称空间还有文件执行过程中产生的#print(globals())可以查看全局的名称空间内名字 # class_name="People" # class_bases=(object,) # class_dic={} #exec运行时会将运行中的产生的名字都丢入岛class_dic的名称空间内,类名称空间 # class_body=""" #exec提取这里面的代码并且运行,模拟python代码的运行过程 # country='China' # def __init__(self,name,age): # self.name=name # self.age=age # # def eat(self): # print('%s is eating' %self.name)
#类名,全局名称空间,类名称空间
# exec(class_body,{},class_dic)#模拟python代码的运行过程,会将运行中的代码名字都丢入岛class_dic的名称空间内
#exec中间的括号内是代表全局的名称空间,模拟类定义阶段定义名称空降操作,讲类定义是的名字丢入到类的名称空间
# People1=type(class_name,class_bases,class_dic)#元类调用赋值给类
# print(People1)#类
#创建类的方式有两种,一种是用class关键字创建,另一种是自定义元类
# 大前提:如果说类也是对象的化,那么用class关键字的去创建类的过程也是一个实例化的过程
# 该实例化的目的是为了得到一个类,调用的是元类
#默认的元类是type,专门产生类用的 #class People: #People=type(类名,父类,类的名称空间)
#创建类的三大要数,类名,父类,类的名称空间
# class_name='People' #类名 # class_bases=(object,) #父类,元组显示在名称空间内 # class_dic={}#类的字典 # class_body=""" #类体代码 # country='China' # def __init__(self,name,age): # self.name=name # self.age=age # # def eat(self): # print('%s is eating' %self.name) # """ # exec(class_body,{},class_dic) # 准备好创建类的三要素 # print(class_name) #类名 # print(class_bases) #父类 # print(class_dic) #类名称空间
#自定义元类 # class Mymeta(type):#不继承type就是一个普通的类 # def __init__(self,class_name,class_bases,class_dic): # print(self)#本体是People # print(class_name) # print(class_bases) # print(class_dic) # super(Mymeta,self).__init__(class_name,class_bases,class_dic)#重用父类功能 # 分析用class自定义类的运行原理(而非元类的的运行原理): #1、拿到一个字符串格式的类名class_name='People' #2、拿到一个类的基类们class_bases=(obejct,) #3、执行类体代码,拿到一个类的名称空间class_dic={...} #4、调用People=type(class_name,class_bases,class_dic) class Mymeta(type): def __init__(self,class_name,class_bases,class_dic):#将元类的格式写入,self是自己建的类 if class_dic.get("__doc__") is None or len(class_dic.get("__doc__").strip()) == 0: raise TypeError("类中必须又文档注释,并且这档注释不能为空")#控制类的名称空间内容 if not class_name.istitle(): raise TypeError("类名首字母必须大写")#控制类的名字情况 super(Mymeta,self).__init__(class_name,class_bases,class_dic) #讲父类的内容传入方式设置,重用父类功能 class People(object,metaclass=Mymeta):#People=Mymeta(类名,基类们,类的名称空间)#完成类的实例化 #定义类的时候会创造空对象,将空对象连同括号内参数一同传给元类的init内 """你好,China""" country="China" def __init__(self,name,age): self.name=name self.age=age def eat(self): print("%s is eating" %self.name)