面向对象进阶----->反射 getattr 和hasattr方法
判断一个对象有没有血缘关系:isinstance() 里面写的是字类对象和父类名用来判断他们的关系
issubclass()是用来判断两个类是不是有继承的关系 ,括号内 写字类名和父类名 可以判断出字类和父类或者爷爷类的关系
class A:
role = "Person"
def __init__(self):
self.money = 500
def func(self):
print("*"*10)
a = A()
print(a.func) #得到是内存地址
# print(a.func())
getattr(a,'func')()
print(getattr(a, 'money'))
class Foo(object): def __init__(self , name): self.name = name class Doo(Foo): def __init__(self,name, age): super().__init__(name) self.age = age f = Foo('alex') d = Doo('laowang ',14) class B:pass class A(B):pass a = A() print(isinstance(a,A)) print(isinstance(a,B)) #isinstance 判断一个对象和一个类有没有血缘关系 isinstance() class C:pass class D(C):pass print(issubclass(C,D)) print(issubclass(D,C))
反射的4个内置函数
getattr() ******
hasattr() ******
strattr() 修改和新建
delattr() 删除一个属性
反射是;使用字符串数据类型的变量名来使用变量
hasattr() 判断一个命名空间中有没有这个名字
getattr()从命令空间内获取这个名字对应的值 从命令空间中获取这个名字的值
hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
需要注意的是name要用括号括起来
getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在就报错,打印出默认值,默认值可选。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号。
class A: role = 'Person' print(getattr(A,'role')) 使用字符串数据类型的变量 访问一个命名空间中的名字 class B: l = '你好' def func(self): print(111) print(getattr(B,'l')) getattr(B,'func')(1) #从类中找方法找的是它的内存地址 你需要加上括号才能调用它 并且传参 self 找一个属性 直接就可以找到这个属性的值 找一个方法找到的就是这个方法的内存地址你可以对这个内存地址进行赋值来及逆行调用 getattr(B,'func')(3) print(hasattr(B,'l')) print(hasattr(B, 'v')) ret = input('>>>') if hasattr(B , ret): print(getattr(B, ret)) hasattr() 判断一个命名空间中有没有这个名字 getattr()从命令空间内获取这个名字对应的值 从命令空间中获取这个名字的值
其实eval类似getattr()方法 可以直接取值 但是一般除了取文件中的内容是不能用eval的 是防止一些错乱所以这个时候就有了反射getattr()方法
不论 hasattr()还是getattr()你所查询判断的内容必须是字符串类型的就是用引号括起来的 就好比你从文件中取出文件但是你的文件是什么类型的呢 是str的 所以需要用引号括起来
hasattr是用来判断 getattr使用来获取的 getattr()来获取的内容是方法的时候必须在最后加上括号括号括号(重要的说三遍)不然会不执行 因为方法执行必须加括号,调用的时候是对象的时候括号内不需要传递参数,如果是类的时候就不需要传递参数
class A: role = 'Person' def func(self): print('*'*self) a = A() print(hasattr(a,'func')) if hasattr(a,'func'): getattr(A, 'func')(3) if hasattr(A,'func') : getattr(a,'func')(5) import os getattr(os,rename)(old, new) a = 1 b = 2 def login(): print('执行了login') def register(): print('执行了register方法') import sys # sys.modules['__main__'], func = input('>>').strip() getattr(sys.modules['__main__'],func)() class A: def b(self): print(111) a = A() fun = input('>>').strip() if hasattr(a,'func'): getattr(a,'func')(1) else : print(2) class A: def __init__(self, name, age, sex, cls): self.name = name self.age = age self.sex = sex self.cls = cls def __len__(self): return 5 a = A('a',33, 'nv', 2) print(len(a)) class D: role = '你好' def func(self): print(111) d = D() # print(hasattr(d,'role')) info = input('》》').strip() if hasattr(d,info): #hasattr用来判断你的内容是不是存储的有这个变量 getattr(D,'func')(1) class B:pass class A(B):pass a = A() print(isinstance(a,A)) print(isinstance(a,B)) #检测到继承的关系 print(isinstance(A,B)) #只能用字类对下个和父类名来判断 print(type(a)is A) #type只能狗单纯的判断类 print(type(a) is B) 判断一个类和另外一个类有没有血缘关系 isinstance() class B:pass class C(B):pass class D(C) :pass print(issubclass(C,D)) print(issubclass(D,C)) #issubclass判断是不是继承 # isinstance()只可以用字类对象和父类名来判断 ,因为判断是不是有血缘关系 print(issubclass(B,C)) #继承和被继承者不能颠倒 class A: role = 'ni' def func(self): print(666) a = A() info = input('>>').strip() if hasattr(a,info): getattr(a,info)() #通过对象是不用传递参数的 但是通过类 是需要传递参数的 def login(): print('执行了login方法') def register(): print('执行了注册功能') import sys func = input('>>').strip() if hasattr(sys.modules['__main__'],func): getattr(sys.modules['__main__'], func)() def login(): print('您在执行login的操作') def register(): print('您在执行reguster的操作') import sys # print(sys.modules['__main__']) func = input('》》').strip() if hasattr(sys.modules['__main__'], func): getattr(sys.modules['__main__'],func)() import time # time.time() print(getattr(time,'time')()) role = 123 print(eval('role')) #但是这个eval除了是去除文件中的信息的时候用到 其他的时候一般是禁止使用的 class A: role = 'Person' def func(self): print('*'*self) ret = input('>>').strip() # print(A.__dict__[ret]) #打印你所输入的类的属性的对应的值 因为你的内容是以字典的形式存储起来的 那么就用__dict__来查看 print(getattr(A,ret)) #从a的命名空间里找一个属性 直接就可以找到这个属性的值 print(getattr(A,'role')) f = getattr(A, 'func');f(10) #也可以这样的简写 从A的命名空间里找一个方法 招待的就是这个方法的内存地址值 A.func(1) 反射you 正常情况下如果可以拿到这个变量 那么如果有有这个变量的字符串形式 就是可以用反射获取到这个值 使用字符串类型的变量名 访问一个命名空间中的名字 找一个属性 直接就可以找到这个属性的值 找到一个方法直接找到的是这个方法的内存的地址 就是你找不论变量还是方法必须是通过字符串类型的来查找 因为你存储文件也是以字符串类型的形式来查找 所以你直接用getattr来查找必须加引号 hasattr() 判断这个空间内有没有这个名字 getattr从命名空间中获取这个名字对应的值 类的反射就是 类可以获取类中的属性和方法 class A: role = 'Perosn' def func(self): print('*'*self) a = A() # print(getattr(a, role)) #你需要以字符串的 类型来查找不然找不到会报错,因为就好比你文件的内容也是以字符串的类型存储的 if hasattr(a,'func'): getattr(A,'func')(10) getattr()
用getattr验证对象是不是含有这个方法 那么不需要传递参数 但是类名验证需要传递参数
#第一种验证对象中含有这个方法 class A: def b(self): print(111) a = A() func = input('>>').strip() if hasattr(a,func): # 验证对象中是否有这个 getattr(a,func)() # 因为是对象名验证的所以不需要传递参数 else: print(333) #下面验证对象是否含有 class A: def b(self): print(111) a = A() func = input('>>').strip() # if hasattr(A, func): # getattr(A,func)() #不传递参数直接会报错 缺少self参数 if hasattr(A, func): getattr(A, func)(a) #如果没有特殊规定这个参数可以随意传递 else : print(333)
类使用类命名空间中的名字
getattr(类名,'名字')
对象使用对象能用的方法和属性
getattr(对象名, '名字')
模块使用模块中的名字
导入模块
getattr(模块名, '名字')
用getattr查看当前位置下的内容地址: (找到地址我们可以根据地址做很多有意义的事)
import sys def bb(): print(666) func = input('>>').strip() if hasattr(sys.modules['__main__'], func): #判读当前位置中是否有func的内容 sys.modules['__main__']是显示当前位置 getattr(sys.modules['__main__'],func)() # 找到位置后根据这个位置来查找这个地址下的方法或者属性 这个事查找方法 别忘了加()
也可以获取模块中内容
def login(): print('执行login功能') def register(): print('执行register功能') import sys # 和python解释器相关的内容都在sys里 print(sys.modules['__main__']) func = input('>>>') if hasattr(sys.modules['__main__'],func): getattr(sys.modules['__main__'],func)()
import time
time.time()
print(getattr(time, 'time')())
import os
os.rename('old','new')
getattr(os,'rename')('old','new') #获取os.rename的功能
内置函数__len__和内置方法len()是唯一对应的关系
就是__len_-中的内容都可以通过len来得到 不论任何值 这个时候如果len得到的是__len__中的内容就不是求长度了
class A: def __init__(self, name, age, sex, cls): self.name = name self.age = age self.sex = sex self.cls = cls def __len__(self): # return len(self.__dict__) return 111 a1 = A('alex', 81, '不详', 2) print(len(a1)) #这个时候就不是得到长度了而是类中的__len__中的返回值
内置的东西
# 都和内置的方法有着千丝万缕的联系
# 字典的存储
# hash
class A:
def __init__(self,name,age,sex,cls):
self.name = name
self.age = age
self.sex = sex
self.cls = cls
def __hash__(self):
return 0
a1 = A('alex',81,'不详',2)
print(hash(a1))