反射,内置方法,

it2022-05-05  123

反射

反射用到的mmp模块

def wahaha():print('wahaha') class QQxing: def __init__(self,name): self.name = name def ADCa(self): print('in ADCa',self.name) # a # b # wahaha # QQxing # getattr('a') import sys print(sys.modules) print(sys.modules[__name__]) print(getattr(sys.modules[__name__],'a')) print(getattr(sys.modules[__name__],'b')) getattr(sys.modules[__name__],'wahaha')() name1='aaa'name2='bbb'name3='ccc'inp=input('>>>')print(inp) class A: Name1 = 'aaa' Name2 = 'bbb' Name3 = 'ccc' def __init__(self,name): self.name=name def func(self): print('in func',self.name)

图示帮助理解

a1=A('ddd')#实例化了一个ddd a1.func()#调用了func函数 in func ddd print(a1.name)#打印函数中名字 ddd getattr(a1,'func')#'func'是字符串类型的变量名 getattr(a1,'func')() #in func ddd 加上括号执行函数 print(getattr(a1,'func'))#打印的是地址 print(getattr(a1,'name'))#打印实例化后,a1对应的名字 if hasattr(A,'Name1'): print(getattr(A,'Name1'))#和hasattr搭配使用 #Name1 print(getattr(A,'Name2')) #Name2 print(getattr(A,'Name3')) #Name3 while True: inp=input('>>>') if hasattr(A,inp): print(inp) 使用字符串数据类型的变量名来操作一个变量的值使用反射获取某个命名空间的值 需要 有一个变量指向这个命名空间的字符串数据类型的名字, 再使用getattr获取值 如果是变量,能直接获得结果 如果是函数,只能拿到内存地址,加上括号就是执行使用类名反射:静态属性,类方法,静态方法使用对象名反射:对象属性,类中的普通方法使用模块名反射:变量,函数,类在自己所在的文件夹中反射全局变量:getattr(sys.modules[__name__],'要反射的名字') import mmp print(mmp.a)#直接使用模块,调用模块中的变量 print(getattr(mmp,'a'))#使用反射,调用模块中的变量a mmp.wahaha()#直接使用模块调用模块中的函数 getattr(mmp,'wahaha')()#使用反射调用模块中的函数 print(mmp.QQxing)#直接使用模块,获取类的内存地址 taibai=mmp.QQxing('太亮')#实例化模块中的类 taibai.ADCa()#实例调用方法 cls=getattr(mmp,'QQxing')#使用反射得到模块中类 ret=cls('光头')#将得到的类实例化 print(ret)#<mmp.QQxing object at 0x0000021FA2805D30> getattr(ret,'ADCa')()#in ADCa 光头 使用反射调用类中的方法 hasattr ******getattr ******setattr ***delattr * import mmp class A: Name1='alex' Name2='taibai' Name3='egon' def __init__(self,name): self.name=name def func(self): print('in func,self.name') A.Country='中国'# A.Name1='alex_NB'# print(A.__dict__)#查看类下的内容 setattr(A,'Country','印度')#将中国改为印度 print(A.__dict__)#查看类下的内容 setattr(A,'Role','Person')#增加一个静态属性 'Role'='Person' print(A.__dict__)#查看类下的内容 delattr(A,'Name1')#删除Name1='alex'的静态变量 print(A.__dict__)#查看类下的内容

内置方法

isinstance(obj,cls)检查是否obj是否是类 cls 的对象issubclass(sub, super)检查sub类是否是 super 类的派生类 a=10 print(isinstance(a,int))#True class F:pass class Foo(F):pass obj=Foo() print(isinstance(obj,Foo))#True print(type(obj)is Foo)#True print(isinstance(obj,F))#True print(type(obj)is F)#False class F:pass class Foo(F):pass print(issubclass(Foo,F))#True print(issubclass(F,Foo))#False 类的内置方法 双下方法 魔术方法对象加上(),可以调用这个类的__call__方法 class Foo: def __call__(self): print('call') Foo()()#call obj=Foo() obj()#相当于调用__call__call 内置函数的len函数是依赖类中的__len__ class Classes: def __init__(self,student_lst): self.student_lst=student_lst def __len__(self):return len(self.student_lst) clas=Classes(['张三','李四','王五']) print(len(clas.student_lst))#不依赖__len__ print(len(clas))#依赖__len__ class Wahaha: def __init__(self,num,name,age): self.num=num self.name=name self.age=age def __len__(self): return len(self.__dict__)#返回类中属性的个数 obj=Wahaha(6,'alex',8) print(len(obj.__dict__))#3 print(len(obj))#3 依赖__len__ __eq__ 判断值是否相等的时候依赖__eq__的结果 class QQxing:pass # def __eq__(self,other):本题中没有用到函数的内容(__eq__ 方法) # if type(self)==type(other) and self.__dict__==other.__dict__: # return True # else: # return False q1=QQxing() q1.name='alex' q2=QQxing() q2.name='egon' print(q1,q2)#两个内存地址不同 print(q1==q2)# 两个自定义对象之间是否值相等,会根据内存地址去判断 面试题 判断值是否相等的时候依赖__eq__的结果,==就是在内部调用了__eq__方法 两个对象的名字和性别相同,那么这两个对象就是同一个人 class Person: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __eq__(self,other): if type(self)==type(other) and self.name==other.name and self.sex==other.sex : return True else:return False p1=Person('松松','',23) p2=Person('松松','',24) p3=Person('小灰灰','',23) print(p1==p2)#True print(p1==p3)#False print(p2==p3)#False hash() 在内存的优化上起到了作用 dict,set 两个对象的名字和性别相同,那么这两个对象就是同一个人,对10个对象进行去重 class Person_lst: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __hash__(self): return hash(self.name+self.sex) def __eq__(self,other): if type(self)==type(other) and self.name==other.name and self.sex==other.sex : return True else:return False l1=[('松松','',23),('松松','',24),('松松','',23),('灰灰','',23),('灰灰','',24),\ ('灰灰','',23),('张三','',23),('李四','',23),('王五','',23),('李六','',23),] # p1=Person_lst(l1) p1=[Person_lst(i[0],i[1],i[2],) for i in l1] p2=list(set(p1)) print(p2) for i in p2: # print(i.__dict__)#以字典的形式打印出来,因为类的空间里就是以这种方式储存的。 print(list(i.__dict__.values()))#将p2(类)空间中的内容打印出来。 class Person_lst:#巧用内置方法 def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __hash__(self): return hash(self.name+self.sex) def __eq__(self,other): if type(self)==type(other) and self.name==other.name and self.sex==other.sex : return True else:return False def __str__(self): # 必须返回一个str数据类型 return ','.join([self.name,self.sex,str(self.age)]) l1=[('松松','',23),('松松','',24),('松松','',23),('灰灰','',23),('灰灰','',24),\ ('灰灰','',23),('张三','',23),('李四','',23),('王五','',23),('李六','',23),] # p1=Person_lst(l1)#不能直接传列表,__init__方法的三个参数传不进去 p1=[Person_lst(i[0],i[1],i[2],) for i in l1]#一次性实例化10个对象 p2=list(set(p1))#利用集合去重 # print(p2)#打印的是地址 for i in p2 :#将筛选过的打印出来 print(i) print(hash(p1[0]))#2590952859388047099 print(hash(p1[1]))#2590952859388047099 print(hash(p1[2]))#9131494265893997627 print(hash(p1[3]))#-5720704507138757199 print(hash(p1[4]))#-5720704507138757199 print(hash(p2[4]))#-8555849577569044973 print(hash(p2[5]))#580991108371939176 print(hash(p2[7]))#5769660943707885971 p1第一个和第二个,第四个和第五个判定为同一个人,所以hash值相等 p2中已经去重了,所以每个人的hash值不相等 hash(obj1)==hash(obj2) and obj1.__eq__(obj2):是重复的 obj1.__hash__()==obj2.__hash__() and obj1.__eq__(obj2):是重复的 py 2.7 class Person: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex person_lst=[Person('egon',i,'male') for i in range(100)] for i in set(person_lst): print(list(i.__dict__.values()))

__str__ __repr__

l=[1,2,3]#实际是列表的实例化a='cba'# 语法糖print(a)print(1) class QQxing:pass q1=QQxing() print(q1)#内存地址 class Course: def __init__(self,name,price,period): self.name=name self.price=price self.period=period def __str__(self): return '*'.join([self.name,str(self.price),self.period])#列表转字符串,用join python=Course('python',19800,'6month') linux=Course('linux',17800,'6month') for i in [python,linux]: print(i)#python*19800*6month linux*17800*6month print(python)#没有__str__方法,打印出来的是内存地址 print('course:%s' % python)#course:python*19800*6month print('a:',str(python))#a: python*19800*6month __str__方法和str(),print() %s 都是息息相关的 class Student: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age def __repr__(self): return self.name stu1=Student('光头','',25) print('学生姓名:%r' % stu1)#学生姓名:光头 print(repr(stu1))#光头 __repr__方法 和repr() %r 都是息息相关的 class Student: def __init__(self,name,sex,age): self.name=name self.sex=sex self.age=age # def __str__(self): # return '&'.join([self.name,self.sex,str(self.age)]) # def __repr__(self): # return self.name def __repr__(self): return ''.join([self.name,self.sex,str(self.age)]) stu1=Student('光头','',25) print('%s' % stu1)#光头:男:25 print('学生:%r' % stu1)#学生:光头:男:25 print(str(stu1))#光头:男:25 print(repr(stu1))#光头:男:25 在没有实现__str__方法的情况下,__repr__能够完全代替__str__的功能 但是__str__不能代替__repr__的工作 在__repr__和__str__都存在的情况下: __repr__方法 和repr() %r 都是息息相关的 __str__方法和str() % r都是息息相关的 *coding:utf_8* format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 'tna':'{obj.type}:{obj.name}:{obj.addr}', 'tan':'{obj.type}*{obj.addr}*{obj.name}', } class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __format__(self,format_spec):#format_spec='nat' if not format_spec or format_spec not in format_dict: format_spec='nat' fmt=format_dict[format_spec]#fmt='{obj.name}-{obj.addr}-{obj.type}' return fmt.format(obj=self)#'{obj.name}-{obj.addr}-{obj.type}'.format(obj=self) 格式化输出 s1=School('清华','北京','公立') print(format(s1,'nat'))#清华-北京-公立 print(format(s1,'tna'))#公立*清华1:北京 print(format(s1,'tan'))#公立*北京*清华1 print(format(s1,'iwejkwocoi'))#清华1-北京-公立 class A:pass o=A() o.name='a' o.addr='b' o.type='c' print('{obj.name}-{obj.addr}-{obj.type}'.format(obj=o))#格式化输出 总结: 反射 —— 明显的简化代码 能拿到的变量名本来就是一个字符串的时候 用户输入的、文件读入的、网络上传输 hasattr 判断某个变量在不在命名空间中 getattr 获取某个名空间中的变量 setattr 给空间中的某个变量赋值、或者创建变量 delattr 从空间中删除某个变量 ***所有的变量都是字符串数据类型的变量名 内置方法 内置方法,内置函数,内置的模块 你自定义的类或者对象 能否利用一些内置函数,内置模块实现功能 你的内置方法是否实现了响应的功能

 

hash()函数就依赖__hash__方法 len()函数就依赖__len__方法 ==函数就依赖__eq__方法 format函数就依赖__format__方法 str,print,%s函数就依赖__str__方法 repr,%r函数就依赖__repr__方法 * 在没有str的时候所有的引用__str__方法的 地方都可以自动引用__repr__方法 set 依赖 __hash__和__eq__方法来完成去重

123

转载于:https://www.cnblogs.com/daofaziran/p/9113884.html


最新回复(0)