一.什么是反射?
反射,又被称为自省,主要是指程序本身可以访问,检测,和修改“自己”,状态或行为的一种能力。
二.python是如何体现这种反射机制的?
通过字符串去操作对象相关的属性,python中,一切皆对象,所有的地方都可以用到反射。
python内部提供了四个实现反射(自省)的函数,这四个函数可以适用于任何的类和对象(这是因为类本身也是一个对象!)
1.hasattr(object,str) 用来检测一个对象中是否有某个字符串对应的方法或者属性。
例如:
l1 = []
print hasattr(l1,"append")
True
#如果一个对象中有以这个字符串命名的属性或者方法,那么就回直接返回True,否则就回返回False。
#在一个列表中是没有keys方法的。
l1 = []
print hasattr(l1,"keys")
False
2.getattr(object,str,defaultstr) 通过一个字符串去获取一个对象的属性或者方法,如果找不到指定的属性或者方法默认情况下会抛出异常。
l1 = [1,2,3]
print getattr(l1,"pop")
#获取l1这个对象的pop方法,结果pop方法就获取到了,在后面加个括号就可以执行。
<built-in method pop of list object at 0x1076097a0>
print getattr(l1,"pop")()
当要在一个对象中查找一个属性或者方法时,这个方法不存在,又不希望直接抛出异常,这时候就要使用getattr的第三个参数,这个参数可以指定如果找不到指定属性或者方法默认返回的值是什么。
l1 = [1,2,3]
print getattr(l1,"aaaaaaa","i dont know")
#在l1这个对象中查找名为aaaaaaa的方法,如果找不到,就返回一个i dont know。
i dont know
3.setattr(object,key,value) 通过字符串的方式,给一个对象创建一个新的属性,同时也可以修改一个对象原来的属性。
class test(object):
def __init__(self):
self.test = "test"
test1 = test()
print test1.test
test
setattr(test1,"test","ayumi")
#修改一个对象中的属性
print test1.test
ayumi
setattr(test1,"aaa","bbb")
#给一个对象添加一个属性。
print test1.aaa
bbb
4.delattr(object,str) 通过字符串删除一个对象中的一个属性或者方法,当被删除的属性不存在时就会报错。
三.__call__,__setattr__,__delattr__,__getattr__
__call__方法用于对象自身的调用。
当一个对象后面加()小括号调用自己的时候,就会触发自身的__call__方法,__call__方法下面的代码就回被执行。
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print "执行了__call__方法"
print self.name
print self.age
ayumi = person("hamasakiayumi","38")
#ayumi现在是一个对象,在对象后面直接加()小括号,就回执行__call__方法下面的代码。
ayumi()
输出:
执行了__call__方法
hamasakiayumi
38
2.__getattr__ 当要调用的属性不存在时,就会触发__getattr__下面的方法。
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print "执行了__call__方法"
print self.name
print self.age
def __getattr__(self, item):
print "此方法或属性不存在"
#当找不到指定属性或者方法的时候,就触发__getattr__方法,print "此方法或属性不存在"
ayumi = person("hamasakiayumi","38")
ayumi.assasasaas
输出:
此方法或属性不存在
3.__setattr__当修改一个对象或者类的属性的时候,会触发__setattr__方法,它本身也用来设置对象中的属性。
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print "执行了__call__方法"
print self.name
print self.age
def __getattr__(self, item):
print item
print "此方法或属性不存在"
#def __setattr__(self, *args, **kwargs):
#print "触发__setattr__方法"
#return object. __setattr__(self,*args,**kwargs)
def __setattr__(self, key, value):
print "触发__setattr__方法"
# self.key=value #这就无限递归了,你好好想想
self.__dict__[key]=value #应该使用它
其实上面这两种写法实现的功能都是一样的,下面这种写法更容易理解,直接修改了__dict__这个属性的字典。
ayumi = person("hamasakiayumi","38")
ayumi.song = "fly high"
#为一个对象增加一个属性,__setattr__方法就被执行了。
print ayumi.song
输出:
触发__setattr__方法
触发__setattr__方法
触发__setattr__方法
fly high
4.__delattr__当删除一个对象中的某个属性,或者某个方法时,会触发__delattr__这个方法。
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print "执行了__call__方法"
print self.name
print self.age
def __getattr__(self, item):
print item
print "此方法或属性不存在"
def __setattr__(self, *args, **kwargs):
print "触发__setattr__方法"
return object. __setattr__(self,*args,**kwargs)
# def __delattr__(self, *args, **kwargs):
# print ‘call func del attr‘
# return object.__delattr__(self, *args, **kwargs)
# 这种写法是继承新式类中实现过的__delattr__方法。
def __delattr__(self, item): #当使用del关键词删除一个属性或者方法的时候,__delattr__下面的代码
print "触发__delattr__方法" 就会被触发。
self.__dict__.pop(item) #这个是删除的动作。
ayumi = person("hamasakiayumi","38")
注意!!__call__,__setattr__,__delattr__,__getattr__这四种方法,系统默认已经定义好了,当有特殊需求的时候,才需要自己去定义。
本文出自 “reBiRTH” 博客,请务必保留此出处http://suhaozhi.blog.51cto.com/7272298/1917254
8.python之面相对象part.6(反射&__call__,__setattr__,__delattr__,__getattr__)
原文地址:http://suhaozhi.blog.51cto.com/7272298/1917254