isinstance(obj,cls) 检查obj是否是cls类的对象
issubclass(sub,super) 检查sub类是否是super类的子类
反射
是用字符串类型的名字 去操作 变量
为什么不用eval()?
name = 1 eval('print(name)') # 1
因为eval()操作的是一个字符串代码,这段字符串我们拿过来对立面的信息什么都不知道,会有很大的安全隐患
而反射只是通过字符串来操作内存里的变量
- setattr
- delattr
- getattr
- hasattr
反射对象的属性和方法
class A: def func(self): print('in func') a = A() a.name = 'alex' a.age = 63 # 反射对象的属性 ret = getattr(a, 'name') # 通过变量名的字符串形式取到的值 print(ret) # 'alex' print(a.__dict__) # 查看对象a中的所有属性 变量名 = input('>>>') # func print(getattr(a, 变量名)) print(a.__dict__[变量名]) #也可以通过这样来调用属性 # 反射对象的方法 a.func() ret = getattr(a,'func') ret() # 执行方法
反射类的属性和方法
class A: price = 20 # 静态属性 @classmethod def func(cls): print('in func')
# 反射类的属性 print(getattr(A,'price')) # 反射类的方法 :classmethod staticmethod if hasattr(A,'func'): getattr(A,'func')()
反射模块的属性和方法
定义模块my.py
day = 'Monday' def wahaha(): print('wahaha')
反射
import my # 反射模块的属性 print(my.day) print(getattr(my,'day')) # 反射模块的方法 getattr(my,'wahaha')()
反射当前模块的属性和方法
def qqxing(): print('qqxing') year = 2018 import sys # print(sys.modules['__main__'].year) # sys.modules查看当前模块的名字 # 反射自己模块中的变量 print(getattr(sys.modules['__main__'],'year')) # 反射自己模块中的函数 getattr(sys.modules['__main__'],'qqxing')() 变量名 = input('>>>') print(getattr(sys.modules[__name__],变量名)) # 一般情况下用__name__变量 获取当前模块的名字
要反射的函数中有参数怎么办?
import time print(time.strftime('%Y-%m-%d %H:%M:S')) # 为时间打上格式 print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S')) # 后面传参就行了
setattr和delattr (不重要)
# setattr 设置修改变量 class A: pass a = A() setattr(a,'name','nezha') setattr(A,'name','alex') print(A.name) print(a.name) # delattr 删除一个变量 delattr(a, 'name') print(a.name) # alex delattr(A,'name') print(a.name) # 报错
类中的几个内置方法
内置的类方法 和 内置的函数之间有着千丝万缕的联系
__repr__ 让字符和数字原形毕露
__str__ 直接打印对象,走的是__str__下的内容
obj.__str__相当于 str(obj)
obj.__repr__ 相当于 repr(obj)
以上两个内置方法返回的必须是字符串,否则报错
class Teacher: def __init__(self,name,salary): self.name = name self.salary = salary def __str__(self): return "Teacher's object :%s"%self.name def __repr__(self): return str(self.__dict__) def func(self): return 'wahaha' nezha = Teacher('哪吒',250) print(nezha) # 打印一个对象的时候,就是调用a.__str__,如果没有,调用的是a.__repr__ print(str(nezha)) print('>>> %s' %nezha) print(repr(nezha)) # print(str(nezha))和此功能一样。repr 是str的备胎,但str不能做repr的备胎 print('>>> %r' %nezha)
%s str() 直接打印 实际上都是走的__str__
%r repr() 实际上都是走的__repr__
如果类中没有__str__却有__repr__方法,%s str()打印出的是__repr__方法,如果__str__和__repr__都没有,打印出来的是Teacher类的内存地址
print(obj), '%s'%obj, str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
repr(),只会找__repr__,如果没有找父类的一般会优先实现__repr__方法
__del__
析构函数: 在删除一个对象之前进行一些收尾工作
class A: def __del__(self): self.f.close() a = A() a.f = open() # 打开文件操作 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中 # del 既执行了这个方法,又删除了变量 del a # a.f 的文件操作符消失在了内存中 但是这个文件仍然打开着 类方法__del__执行了关闭文件操作
__call__ 挺有用的
一个对象后加上括号()相当于执行了__call__方法
class A: def __init__(self,name): self.name = name def __call__(self): ''' 打印这个对象中的所有属性 :return: ''' for k in self.__dict__: print(k,self.__dict__[k]) a = A('alex')()
输出: