python进阶-面向对象编程三:类和对象的反射方法
类的内置方法:__getattr__,__setattr__,__delattr__
# __getattr__为内置方法,当使用点号[获取实例属性时],如果属性不存在就自动调用__getattr__方法,如类Foo()的对象f.name # __setattr__当[设置类实例属性时]自动调用,如f.name=5 就会调用__setattr__方法 self.[name]=5 # 这个类是从dict继承来的,是dict的超类 class Foo: def __init__(self,name): self.name=name def hello(self): print("hello") #获取实例属性时,属性不存在的情况自动调用 def __getattr__(self, item): # 打印属性不存在时的属性和类型 print("%s %s"%(item,type(item))) # 当[设置类实例属性时]自动调用 def __setattr__(self, key, value): print(self,key,value) if not isinstance(value,str): raise TypeError("must be str") else: self.__dict__[key]=value def __delattr__(self, item): self.__dict__.pop() f=Foo("adamanter") f.hello() f.name #类有这个属性,不会调用__getattr__ f.food #类没有这个属性,会调用__getattr__,显示food <class 'str'>,属性是food,类型是str f.eat #类没有这个属性,会调用__getattr__,显示eat <class 'str'>,属性是eat,类型是str f.name = "antonio" #设置调用__setter__,打印本身<__main__.Foo object at 0x1011bff28> name antonio,也放入了f字典 #f.age =18 #报错,因为不符合设置属性时候,我们判断的是必须是字符串,因此抛出:must be str print(Foo.__dict__) #里面有hello函数 print(f.__dict__) #里面有{'name': 'adamanter'} # {'__setattr__': <function Foo.__setattr__ at 0x10842fbf8>, '__init__': <function Foo.__init__ at 0x10842fae8>, # '__getattr__': <function Foo.__getattr__ at 0x10842fb70>, '__dict__': <attribute '__dict__' of 'Foo' objects>, # '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__delattr__': <function Foo.__delattr__ at 0x10842fc80>, # '__doc__': None, 'hello': <function Foo.hello at 0x10842fa60>, '__module__': '__main__'} # {'name': 'adamanter'}
python面向对象中的反射:hasattr,getattr,setattr,delattr
# python面向对象中的反射:通过字符串的形式操作对象相关的属性。 # python中的一切事物都是对象(都可以使用反射) # 四个可以实现自省的函数 # 下列方法适用于类和对象(一切皆对象,类本身也是一个对象) # 基于类的反射 class People: country="china" def __init__(self,name): self.name=name def walk(self): print("%s walk",self.name) h=People("ada") # 利用布尔值返回类或对象有没有这个属性,hasattr返回布尔值 print(hasattr(People,"country")) print(hasattr(h,"country")) print(hasattr(h,"walk")) # True # True # True #获取类或对象的某个属性,getattr回值就是获取的属性值或绑定的方法 res1=getattr(People,"country") print(res1) res2=getattr(h,"country") print(res2) res3=getattr(h,"walk") print(res3) # china # china # <bound method People.walk of <__main__.People object at 0x10f7e75f8>> #设置类或对象的某个属性并查看,setattr返回None,但是属性已经添加 sss = setattr(h,"age",18) print(sss) print(h.__dict__) # None # {'name': 'ada', 'age': 18} #删除类或对象的某个属性并查看,delattr返回None,但是属性已经删除 ddd = delattr(h,"age") print(ddd) print(h.__dict__) # None # {'name': 'ada'} 因为没有age属性,不可修改属性
基于模块的反射
# 反射当前模块的属性 import sys x=1111 class Foo: pass def s1(): print('s1') def s2(): print('s2') this_module=sys.modules[__name__] print(this_module) # <module '__main__' from '/Users/Alex/PycharmProjects/hellotest/python/反射.py'> #这句话所做的操作:遍历s1在不在this_module 的字典__dict__中 print(hasattr(this_module,'s1')) print(getattr(this_module,'s2')) print(this_module.s1) print(this_module.s2) # True # <function s2 at 0x101678f28> # <function s1 at 0x1014a0f28> # <function s2 at 0x101678f28> # import importlib # t=importlib.import_module("time") # print(t.time()) #导入当前路径下包impag下的hello.py # x=importlib.import_module("impag.hello") # 字符串导入模块,官方不推荐 # m=input("please input your module:") # m1=__import__(m) # print(m1) # print(m1.time())
重写自定制列表的append和insert方法
class List(list): def append(self,object:str): if not isinstance(object,int): raise TypeError("must int") super().append(object) def insert(self, index: int, object): if not isinstance(object,int): raise TypeError("must int") super().insert(index,object) l=List([1,2,3]) print(l) # [1, 2, 3] l.append(4) #会调用类本身的append方法 print(l) # [1, 2, 3, 4] # l.append("hello") 我们重写了append方法,要求他只能接受int # raise TypeError("must int") l.insert(0,-1) #第一个0是索引,必需是int,第二个规定是int # l.insert(0,"hello") #报错,因为我们重写了增加和插入方法,非int类型插入报错,必须是int类型 print(l) # [-1, 1, 2, 3, 4]