# 类的内置方法、双下方法 #1.对象(): 触发__call__方法 #2.len(对象):触发__len__方法: return len(对象) --> 返回对象的长度 # return len(self.__dict__) -->返回各个属性的长度、 #3.obj1 == obj2: 触发__eq__(self,other)方法: # class A: # def __init__(self,name): # self.name = name # def __eq__(self, other): # if type(self) == type(other)and self.name == other.name: # return True # else:return False # obj1 = A('alex') # obj2 = A('alex') # print(obj1 == obj2) #4.hash(对象) -->触发__hash__方法。 # 去重:set(对象)-->触发__hash__方法及__eq__方法。 #100个人,实现去重。(姓名和性别一样,年龄可能会不一样) #set()去重机制:1.首先判断hash值是否相同,同一个人,姓名性别不会变但是年龄会变,所以同一个人一般返回的都是不一样的hash值, # set无法去重。所以只判断姓名和性别: # 只返回姓名和性别字符串拼接后的hash值,如果不同则放入各自内存地址中,如果相同,继续判断。 # 2.判断姓名和性别的值是否相同,触发__eq__方法,如果相同,返回True,set实现去重,如果不同再放入各自的内存地址。 # class A: # def __init__(self,name,sex,age): # self.name = name # self.sex = sex # self.age = age # def __hash__(self): # return hash(self.name+self.sex) #只判断姓名和年龄,只返回它们的hash值。 # def __eq__(self, other): # if type(self) == type(other)and self.name == other.name and self.sex == self.sex: # return True #只判断姓名和年龄的值,如果再为真则返回真,去重。 # else:return False # # person_list = [A('alex','male',i+1) for i in range(100)] # print(set(person_list)) #5.print(对象名)/str(对象名)/'%s'% 对象名 :触发__str__方法:return ''.join([self.name,self.sex,str(self.age)]) #6.repr(对象名)/'%r'%对象名:触发__repr__方法:1.当__str__不在时,可以完全替代__str__。 # 被print(对象名)/str(对象名)/'%s'% 对象名 这些触发。 # 2.__str__存在时,各自执行各自的功能。 # 3.不可反向,__str__不能替代__repr__ # class A: # def __init__(self,name,age,sex): # self.name = name # self.age = age # self.sex = sex # def __str__(self): # return '|'.join([self.name,str(self.age),self.sex]) # def __repr__(self): # return '*'.join([self.name,str(self.age),self.sex]) # obj = A('alex',19,'男') # print(obj) #如果__str__不存在,则执行__repr__方法。 # print(repr(obj))
#反射:使用字符串形式的变量来操作变量的值 #一、getattr + hasattr #A . B 的形式的,可以用getattr找到。 #1.用类反射,静态属性、类方法、静态方法。 # class A: # name = 'taibai' # age = 19 # def __init__(self,sex,school): # self.sex = sex # self.school = school # def func(self): # print('我是func函数') # print(getattr(A,'name')) #变量名一定是字符串形式的。 #与hasattr配合使用。 # content = input('请输入您要查找的属性').strip() # if hasattr(A,content): # print(getattr(A,content)) # else: # print('没有此属性') #2、用对象反射, 对象属性,类中的普通方法。 # obj = A('male','oldboy') # print(getattr(obj,'sex')) # getattr(obj,'func')() #调用方法,getattr得到的是方法名的内存地址,后面再加括号即可调用。 #3、用模块反射,先导入模块,然后调用其中的类、变量和方法。 # import mmm # print(getattr(mmm,'a')) #mmm.a # getattr(mmm,'wahaha') #mmm.wahaha # getattr(getattr(mmm,'QQxing')('alex'),'ADCa')() #4、当前模块中用反射操作全局变量。见mmm文件。 # import mmm #执行getattr(sys.modules[__name__],'wahaha')() #此处的__name__由于在外面调用变成了'mmm',本文件中导入了mmm, 可以正常调用。 #一个文件调用另外一个文件(模块)的时候,模块中的sys.path和sys.modules中的_main_都会被改变成调用者的路径。 #所以在导入模块(sys.path中)和调用属性或方法(sys.modules['_main_'])时一定要写活。 #如:导入当前文件夹下的login:正常情况下直接import login就可以了,但是当被别的文件夹的文件当成模块调用时则找不到login了, # 因为sys.path下的上级目录被改变成了调用者的上级目录。 #解决: from core.login import login #同理,sys.modules['_main_']在被别的文件调用的时候,'__main__'对应的值也会变成调用文件的路径,找不到被调用的属性或方法了。 #解决: sys.modules[__name__] #二、另外两个反射方法:setattr/delattr # setattr(A,'name','alex') #有则修改。无则添加。 # print(A.name) # delattr(A,'name') #删除属性 # print(A.name)