getattr getattribute setattr hasattr delattr

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

posted @ 2018-07-17 17:33  扫驴  阅读(279)  评论(0编辑  收藏  举报