getattr是返回对象属性value的函数,用法:getattr(object,attribute_name[,default])
如果对象拥有属性,则返回属性value,如果对象没有该属性并且也没有定义__getattr__方法的时候,则要么抛出异常要么有default参数返回default值。
但是,当类中定义了__getattr__的时候,在属性不存在的情况下,getattr就会调用__getattr__方法看看能不能获取到value
以上结论适用于心事累也适用于就是累
class C(): a = 'abc' def __getattr__(self, name): print ('hhh') if name == 'adult': return True else: raise AttributeError(name) a=C() aa=getattr(a,'a')#aa为'abc' b=a.adult#打印hhh,b为True c=getattr(a,'adult',6)#打印hhh,c为True d=getattr(a,'ss',4)#打印hhh,d为4 d=getattr(a,'ss')#打印hhh,抛出异常
object.__getattribute__(self, name)
实例instance
通过instance.name
访问属性name
,__getattribute__
方法一直会被调用,无论属性name
是否追溯到。如果类还定义了__getattr__
方法,除非通过__getattribute__
显式的调用它,或者__getattribute__
方法出现AttributeError
错误,否则__getattr__
方法不会被调用了。如果在__getattribute__(self, attr)
方法下存在通过self.attr
访问属性,会出现无限递归错误。
如下所示,ClassA
中定义了__getattribute__
方法,实例insA
获取属性时,都会调用__getattribute__
返回结果,即使是访问__dict__
属性。
class ClassA(object): def __init__(self, classname): self.classname = classname def __getattr__(self, attr): return('invoke __getattr__', attr) def __getattribute__(self, attr): return('invoke __getattribute__', attr) insA = ClassA('ClassA') print(insA.__dict__) # ('invoke __getattribute__', '__dict__') print(insA.classname) # ('invoke __getattribute__', 'classname') print(insA.grade) # ('invoke __getattribute__', 'grade')
还有一个是setattr,如果类自定义了__setattr__
,对实例属性的赋值就会调用它。需要注意的是,在__setattr__
下还有self.attr
的赋值操作就会出现无线递归__setattr__
的情况。自己实现__setattr__
有很大风险,所以一般情况都还是继承object
类的__setattr__
方法。
class ClassA(object): def __init__(self, classname): self.classname = classname def __setattr__(self, name, value): # self.name = value # 如果还这样调用会出现无限递归的情况 print('invoke __setattr__') insA = ClassA('ClassA') # __init__中的self.classname调用__setattr__。 # invoke __setattr__ print(insA.__dict__) # {} insA.tag = 'insA' # invoke __setattr__ print(insA.__dict__) # {}
与getattr()函数会调用__getattr__类似,setattr()函数也会调用__setattr__。setattr(object, name, values)
而hasattr就比较简单了,只是一个简单的判断
18年10月23日更新:
关于hasattr的原理:
hasattr的判断依据并不是以dir()所返回的列表为依据。
比如:
#!/usr/bin/env py3 class a: pass print (dir(a)) print (hasattr(a,"mro"))
dir(a),返回的列表并不包含mro元素,但是用hasattr查看却是true
也就是说,如果hasattr(a,x)函数所有返回ture的属性x组成一个集合,那么,dir()所返回的列表,是这个集合的一个子集
再比如:
#!/usr/bin/env py3 class a: ss=3 def __getattr__(self, name): if name == 's': return 5 aa=a() print (dir(aa))#列表中不包含s print (hasattr(aa,"s"))#返回true
delattr是用来删除属性
需要注意的是他只能用来删除实例属性,删除类属性将报错
#!/usr/bin/env py3 class a: ss=3 def __init__(self): self.k=4 def __getattr__(self, name): if name == 's': return 5 aa=a() delattr(aa,'k') #delattr(aa,'ss')#报错 #delattr(aa,'s')#报错
参考:
https://www.cnblogs.com/elie/p/6685429.html