一. 反射
什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
反射就是用字符串数据类型的变量名去访问变量.
反射中适用于类和对象的方法:
getattr
setattr
hasattr
delattr
反射情景:
类名反射 : 静态属性 类属性 静态方法
对象反射: 对象属性 对象方法
模块: 模块中的方法
自己的模块中
反射的参数:
getattr : (命名空间 , ' 变量名 ')
setattr : (命名空间 , ' 变量名 ' , 新值)
hasattr : (命名空间 , ' 变量名 ')
delattr : (命名空间 , ' 变量名 ')
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) print(hasattr(obj,'name')) #检测是否含有某属性 print(hasattr(obj,'say_hi')) #检测是否含有某属性 n=getattr(obj,'name') #获取属性 print(n) func=getattr(obj,'say_hi') #获取属性 func() print(getattr(obj,'aaaaaaaa','不存在啊')) #报错 setattr(obj,'sb',True) # #设置属性 setattr(obj,'show_name',lambda self:self.name+'sb') # #设置属性 print(obj.__dict__) print(obj.show_name(obj)) delattr(obj,'age') # # 删除属性 delattr(obj,'show_name') # # 删除属性 delattr(obj,'show_name111')#不存在,则报错 print(obj.__dict__)
类也是对象
class Foo(object): staticField = "boy" def __init__(self): self.name = 'peiqi' def func(self): return 'func' @staticmethod #静态方法 def bar(): return 'bar' print (getattr(Foo, 'staticField')) print (getattr(Foo, 'func')) print (getattr(Foo, 'bar'))
反射当前模块
还可以导入其他模块,利用反射查找该模块是否存在某种方法.
import sys def s1(): print('s1') def s2(): print ('s2') this_module = sys.modules['__main__'] #__main__表示当前文件 print(hasattr(this_module, 's1')) #判断's1'是否在当前文件的方法名中 getattr(this_module, 's2')() #取出
二. 内置方法/魔术方法/双下方法
__名字__ 不是被直接调用的
间接调用: 内置函数/面向对象中的特殊语法/python提供的语法糖(语法糖: 相对简单的语法)
__call__ : 通过 对象() 调用 用类写装饰器
__len__ : len(obj) , 要求obj必须实现了__len__ , 要求这个方法的返回值必须是数字int类型
__new__ : 在实例化的过程中,最先执行的方法, 在执行__init__之前, 用来创造一个对象,构造方法
__init__ : 在实例化的过程中,在__new__执行之后, 自动触发的一个初始化方法
__str__ : str(obj) ,要求必须事项__str__, 要求这个方法的返回值必须是字符串str类型
可在 : print %s str中使用
__repr__ : 是__str__的备胎, 如果有__str__方法,那么 print %s str 都会先去执行__str__方法,并且使用__str__的返回值
如果没有__str__, 那么 print %s str 都会执行__repr__方法
__repr__ 可在 :repr(obj) , %r 中使用
在子类中使用__str__,先找子类的__str__,如果没有的话就向上面的父类里面找__str__方法,只要父类不是object,并且父类中有__str__方法,就执行父类的__str__
但是如果除了object之外的父类都没有__str__方法, 就执行子类的__repr__方法,如果子类没有__repr方法__,就像上面的父类找__repr__方法,如果在object类之前都没有__repr__方法,就执行object类中的__str__方法.
class A: def __init__(self,name): self.name = name def __str__(self): return '**%s**'%self.name def __repr__(self): return self.name class B(A): def __init__(self,name): self.name = name def __repr__(self): return '***' a = B('xxx') print(a) print(str(a),repr(a)) print('%s | %r'%(a,a)) class A: def __init__(self,name): self.name = name # def __str__(self): # return '**%s**'%self.name def __repr__(self): return self.name class B(A): def __init__(self,name): self.name = name def __repr__(self): return '***' a = B('xxx') print(a) print(str(a),repr(a)) print('%s | %r'%(a,a))
构造方法 申请一个空间
析构方法 释放一个空间
某对象借用了操作系统的资源,还要通过析构方法归还回去 : 文件资源 网络资源
# 垃圾回收机制 class A: def __del__(self): # 析构方法 del A的对象 会自动触发这个方法 print('执行我了') a = A() del a # 对象的删除 del print(a) class File(): # 处理文件的 def __init__(self,file_path): self.f = open(file_path) self.name = 'xd' def read(self): self.f.read(1024) def __del__(self): # 是去归还/释放一些在创建对象的时候借用的一些资源 # del 对象的时候 程序员触发 # python解释器的垃圾回收机制 回收这个对象所占得内存的时候 python自动触发的 self.f.close() f = File('文件名') f.read() # 不管是主动还是被动,这个f对象总会被清理掉,被清理掉就触发__del__方法,触发这个方法就会归还操作系统的文件资源
在内置模块中
有一些特殊的方法, 要求对象必须事现__getitem__/__setitem__才能使用
class B: def __init__(self,lst): self.lst = lst def __getitem__(self, item): return self.lst[item] def __setitem__(self, key, value): self.lst[key] = value def __delitem__(self, key): self.lst.pop(key) b = B(['111','222','ccc','ddd']) print(b.lst[0]) #__getitem__ print(b[0]) b[3] = 'xxx' #__setitrm__ print(b.lst) del b[2] #__delitem__ print(b.lst)
hash方法:
底层数据结构基于hash值寻址的优化操作
hash是一个算法
hash能够把某一个要存在内存里的值经过一系列计算, 保证不同值的hash结果是不一样的
对同一个值在多次执行python代码的时候hash值是不同的, 但对同一个值, 在同一次执行python代码的时候hash值永远不变
集合去重复原理
__eq__方法
class A: def __init__(self,name,age): self.name = name self.age = age def __eq__(self, other): if self.name == other.name and self.age == other.age: return True a = A('xd',83) aa = A('xd',83) aa2 = A('xd',83) aa3 = A('xd',83) aa4 = A('xd',83) aa5 = A('xd',83) aa6 = A('xd',83) print(a,aa) print(aa3 == aa == aa4)
可以判断某一个对象的某一个参数和其他对象的相同位置参数是否相同