Python 基础 三 反射
今天我们先介绍一下反射这个概念,啥是反射?反射就是自己检测自己。在我们Python的面向对象中的反射是啥意思呢?就是通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
在Python中四个产生反射的函数,分别是:hasattr();getattr();setattr();delattr();
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
hasattr((object, name, default=None))
判断object中有没有一个name字符串对应的方法或属性
def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass getattr(object, name, default=None)
def setattr(x, y, v): # real signature unknown; restored from __doc__ """ Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v'' """ pass setattr(x, y, v)
def delattr(x, y): # real signature unknown; restored from __doc__ """ Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y'' """ pass delattr(x, y)
四种方法的演示:
class BlackMedium: feature='Ugly' def __init__(self,name,addr): self.name=name self.addr=addr def sell_house(self): print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name) def rent_house(self): print('%s 黑中介租房子啦,傻逼才租呢' %self.name) b1=BlackMedium('万成置地','回龙观天露园') #检测是否含有某属性 print(hasattr(b1,'name')) print(hasattr(b1,'sell_house')) #获取属性 n=getattr(b1,'name') print(n) func=getattr(b1,'rent_house') func() # getattr(b1,'aaaaaaaa') #报错 print(getattr(b1,'aaaaaaaa','不存在啊')) #设置属性 setattr(b1,'sb',True) setattr(b1,'show_name',lambda self:self.name+'sb') print(b1.__dict__) print(b1.show_name(b1)) #删除属性 delattr(b1,'addr') delattr(b1,'show_name') delattr(b1,'show_name111')#不存在,则报错 print(b1.__dict__) 四个方法的使用演示
为啥要使用反射机制呢?
好处一:实现可插拔机制(就是你与一个人一起开发一个项目若一个人暂时有时不能做他自己负责的项目但你要使用调用他的某些功能,so ,你就可以使用这个反射拉)
总之反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
好处二:动态导入模块(基于反射当前模块成员)
# from m1 import t # t.test1() module_t = __import__('m1.t') # 实质只是导入了最顶层的那个模块m1 print(module_t) # <module 'm1' from 'C:\Users\lenovo\Desktop\Py_fullstack_s4\pythonday15\m1\__init__.py'> # module_t.test1() #AttributeError: module 'm1' has no attribute 'test1' # module_t.t.test1() import importlib m = importlib.import_module('m1.t') # <module 'm1.t' from 'C:\Users\lenovo\Desktop\Py_fullstack_s4\pythonday15\m1\t.py'> print(m) m.test1() m._test2() #只有 import * 的时候才是导入会报错误
二、__setattr__;__getattr__;__delattr__;的使用
class Foo: x=1 def __init__(self,y): self.y=y def __getattr__(self, item): print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value): print('----> from setattr') # self.key=value #这就无限递归了,你好好想想 # self.__dict__[key]=value #应该使用它 def __delattr__(self, item): print('----> from delattr') # del self.item #无限递归了 self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行 f1=Foo(10) print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值 f1.z=3 print(f1.__dict__) #__delattr__删除属性的时候会触发 f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作 del f1.a print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发 f1.xxxxxx