反射:
用字符串数据类型的变量名来访问这个变量的值
反射的方法:
getattr hasattr setattr delattr
getattr: 命名空间.方法名或属性 == getattr(命名空间,'方法名或属性') 获得类中变量的值 若变量不存在则报错
hasattr: 判断类中指定变量是否存在,返回bool值 可以配合getattr使用
class Student: ROLE = 'STUDENT' @classmethod def check_course(cls): print('查看课程了') @staticmethod def login(): print('登录') # 反射查看属性 # print(Student.ROLE) # print(getattr(Student,'ROLE')) # 反射调用方法 方法名不对的时候会报错 # getattr(Student,'check_course')() # 类方法 # getattr(Student,'login')() # 静态方法 num = input('>>>') if hasattr(Student,num): 判断方法名在指定类中是否存在,返回bool值 getattr(Student,num)()
####getattr用途很广泛,基本命名空间.方法名或属性名 这类语句都可以用getattr替代 比如
# import os # # os.rename('__init__.py','init') # # getattr(os,'rename')('init','__init__.py') # == os.rename # rename = os.rename # rename2 = getattr(os,'rename') # rename2('__init__.py','init') # os.rename('__init__.py','init') # rename('init','init2') # os.rename('init','init2')
####反射自己模块中的内容 找到自己当前文件所在的命名空间
def wahaha():
print('wahaha')
def qqxing():
print('qqxing')
wahaha() qqxing() import sys print(sys.modules) # import 都相当于导入了一个模块 #模块哪个导入了 哪个没导入 在我的python解释器里应该记录下来 import sys #是一个模块,这个模块里的所有的方法都是和python解释器相关的 # sys.modules #这个方法 表示所有在当前这个python程序中导入的模块 # '__main__': <module '__main__' from 'D:/sylar/python_workspace/day20/4.反射.py'> #自身模块在modules中的键值对 print(sys.modules['__main__']) my_file = sys.modules['__main__'] my_file.wahaha() my_file.qqxing() # 'qqxing' # 'wahaha' getattr(my_file,'wahaha')() getattr(my_file,'qqxing')()
setattr:修改名称
delattr:删除指定方法或属性
class A: def __init__(self,name): self.name = name a = A('alex') # a.name = 'alex_SB' # getattr(a,'name') setattr(a,'name','alex_SB') #修改对象属性 print(a.name) print(a.__dict__) del a.name print(a.__dict__) delattr(a,'name') #删除对象属性 print(a.__dict__)
__名字__
类中的特殊方法\内置方法
双下方法
魔术方法 magic_method
类中的每一个双下方法都有它自己的特殊意义
__call__ 相当于 对象()
__len__ len(obj)
__new__ 开辟内存空间的 类的构造方法
写一个单例类=
__del__ 析构方法,与__new__相对应 垃圾回收机制
所有的魔术方法都是在外部执行内置函数或者特殊语句而自动在内部执行的,不需要在外部额外出发
__call__:
class A: def __call__(self, *args, **kwargs): print('执行__call方法了') def call(self): print('执行call方法了') class B: def __init__(self,cls): print('在实例化A之前做一些事情') self.a = cls() self.a() print('在实例化A之后做一些事情') a = A() a() # 对象() == 相当于调用__call__方法 a.call() A()() # 类名()() ,相当于先实例化得到一个对象,再对对象(),==>和上面的结果一样,相当于调用__call__方法 B(A) 将A类当做参数传进B类进行实例化
__len__:
# 内置函数和类的内置方法是有奸情的 # len(dict) # len(tuple) str list set class mylist: def __init__(self): self.lst = [1,2,3,4,5,6] self.name = 'alex' self.age = 83 def __len__(self): print('执行__len__了') return len(self.__dict__) l = mylist() print(len(l)) # len(obj)相当于调用了这个obj的__len__方法 # __len__方法return的值就是len函数的返回值 # 如果一个obj对象没有__len__方法,那么len函数会报错
__new__:
__new__ ==> 构造方法
__init__ ==>初始化方法
class Single: def __new__(cls, *args, **kwargs): # print('在new方法里') obj = object.__new__(cls) print('在new方法里',obj) return obj def __init__(self): print('在init方法里',self) # 1.先执行__new__方法,开辟一个属于对象的空间 # 2.把对象的空间传给self,执行init # 3.将这个对象的空间返回给调用者 obj = Single()
单例类:
class Cls: __COND=None def __new__(cls, *args, **kwargs): if not Cls.__COND : Cls.__COND=object.__new__(Cls) return Cls.__COND def __init__(self,name): self.name=name c1=Cls('alex') c2=Cls('kangkang') print(c1) print(c2) #两次打印的内存地址一样,说明只开辟了一个对象空间 print(c1.name) print(c2.name) #因为只开辟了一个对象空间,所以后续实例化的对象属性会覆盖前面的属性
__del__ 析构方法 垃圾回收机制
#构造方法 申请一个空间 #析构方法 释放一个空间之前执行 #某对象借用了操作系统的资源,还要通过析构方法归还回去 : 文件资源 网络资源 #垃圾回收机制 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 = 'alex' def read(self): self.f.read(1024) def __del__(self): # 是去归还/释放一些在创建对象的时候借用的一些资源 # del 对象的时候 程序员触发 # python解释器的垃圾回收机制 回收这个对象所占得内存的时候 python自动触发的 self.f.close() f = File('文件名') f.read() #不管是主动还是被动,这个f对象总会被清理掉,被清理掉就触发__del__方法,触发这个方法#就会归还操作系统的文件资源 #python解释器在内部就能搞定的事儿 #申请一块儿空间 操作系统分配给你的 #在这一块儿空间之内的所有事儿 归你的python解释器来管理 a = 1 del a 对象 --> 内存 f = open('wenjian') # python --> 操作系统 --> 硬盘里的文件 --> 文件操作符 f.close() # 文件操作符 del f