一、今日内容总结
1.反射
使用字符串数据类型的变量名来操作一个变量的值。
#使用反射获取某个命名空间中的值,
#需要
#有一个变量指向这个命名空间
#字符串数据类型的名字
#再使用getattr获取值,
#如果变量能直接获取结果
#如果是函数,只能拿到内存地址,加上括号就是执行
#使用类名反射: 静态属性、类方法、静态方法
#使用对象名反射: 对象属性、绑定对象方法
#使用模块名反射: 变量、函数、类
#在自己所在文件中反射全局变量: getattr(sys.modules[__name__],'要反射的名字')
#getattr
#hasattr
#setattr
#delattr
# import mmm # print(mmm.a) # 直接使用模块调用模块中的变量 # print(getattr(mmm,'a')) # 使用反射调用模块中的变量a # print(getattr(mmm,'b')) # 使用反射调用模块中的变量b # mmm.wahaha() # 直接使用模块调用模块中的函数 # getattr(mmm,'wahaha')() # 使用反射调用模块中的函数 # print(mmm.QQxing) # 直接使用模块获取类的内存地址 # taibai = mmm.QQxing('光头') # 实例化模块中的类 # taibai.ADCa() # 实例调用方法 # cls = getattr(mmm,'QQxing') # 使用反射获取模块中的类 # obj = cls('光头') # 使用反射得到的类进行实例化 # print(obj) # getattr(obj,'ADCa')() # 使用反射调用类中的方法 # hasattr ****** # getattr ****** # setattr *** # delattr * # import mmm class A: Name1 = 'alex' Name2 = 'egon' Name3 = 'guangtou' def __init__(self,name): self.name = name def func(self): print('in func',self.name) # A.Country = '中国' # 增 # A.Name1 = 'alex_sb' # 改 # # setattr # print(A.__dict__) # setattr(A,'Country','印度') # print(A.__dict__) # # 'Role' = 'Person' # setattr(A,'Role','Person') # print(A.__dict__) # delattr(A,'Name1') # print(A.__dict__)
2.__call__
# 对象加上(),可以触发这个类的__call__方法。
class Call_test: def __call__(self): print('I AM CALL') c1 = Call_test() c1()
3.__len__
# 内置函数len函数是依赖于类中的__len__()
#__len__(self): class Wahaha: def __init__(self, num, age, sex): self.num = num self.age = age self.sex = sex def __len__(self):return len(self.__dict__) obj = Wahaha(3, 12, 'male') print(len(obj))
4.__str__和__repr__
# 在没有实现__str__时,__repr__可以完全替代__str__
# 在没有实现__repr__时,__str__不能替代__repr__
# 在两者都实现的情况下:
#__str__方法和str()、%s、print() 等息息相关
#__repr__方法和repr()、%r等息息相关
# 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) # # s1=School('oldboy1','北京','私立') # print(format(s1,'nat')) # print(format(s1,'tna')) # print(format(s1,'tan')) # print(format(s1,'asfdasdffd')) # class A:pass # o=A() # o.name = 'a' # o.addr = 'b' # o.type = 'c' # print('{obj.name}-{obj.addr}-{obj.type}'.format(obj = o))
5.__hash__ #hash()在优化内存中起到作用
6.__eq__
# 是判断值是否相等的时候依赖__eq__的结果
# 如果没有定义__eq__两个对象的值是否相等,会默认根据他们的内存地址是否相等判断
# Person class # name age sex # 两个对象 的name 和 sex相同,那么这两个对象就是相同的对象 # 对100个对象进行去重 class Person: def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name==other.name and self.sex == other.sex: return True else:return False def __repr__(self): return '|'.join([self.name, str(self.age), self.sex]) obj_li = [] for i in range(100): obj_li.append(Person('alex', i, 'male')) print(obj_li) print(set(obj_li)) # hash是否相等,值是否相等 __hash__值相等,__eq__值也相等
# set()集合去重的内部机制:先判断hash值是否相同,如不同,直接重新开辟空间存储,如相等,再通过__eq__判断值是否相同,相同则直接丢弃,不相同,则在附近开辟内存空间存储。
7.isinstance和issubclass
# isinstance 是判断一个对象是否属于某个类或其父类
#issubclass是判断一个类是否是另一个类的子类,注意前后顺序,子类在前,父类在后。
二、预习和扩展
1、__del__
# 析构方法,当对象在内存中释放时,会自动触发执行。
#一个对象有用户级与内核级两种资源
当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源。
2、__slots__ (子类不继承,除非子类类定义)
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__
变量,来限制该class实例能添加的属性:
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
3、__module__和__class__
#__module__表示当前操作的对象在哪个模块
#__class__表示当前操作的对象是哪个类的实例化
4.通过type生成类:
# A = type('A',(object,),{'func':func})
# a1 = A()
# a1.func()
A = type('A',(object,),{'func':lambda self:print(666)})
a1 = A()
a1.func()