python中面向对象之内置方法:__getattribute__和__getattr__、__setattr__、__delattr__的理解和用法

getattribute__和__getattrsetattr、__delattr__是object类的内置方法。
1、__getattribute__是使用属性的时候会调用,如果想拦截属性,可以重写该方法。

class Person(object):
    """hahhahhaa"""
    def __getattribute__(self, item):
        print("设置对象的属性")
        return object.__getattribute__(self, item)
    
p = Person()
p.name = '张三'  
print(p.name)  #使用了p.name这个属性,则此时会去调用__getattribute__这个属性,由于进行了重写,故根据就近原则,直接调用自己类中定义的__getattribute__方法,可以通过重写方法体来控制返回的属性值

如果使用的属性不存在,先去调用__getattribute__方法,在return object.getattribute(self, item)时,由于object.getattribute(self, item)去调用父类的__getattribute__(self, item),找不到,则不会继续return,而是去执行__getattr__这个方法,如果不重写__getattr__方法,则object类中的该方法会直接抛一个异常。可以通过重写__getattr__这个方法来控制输出的结果。

class Person(object):
    """hahhahhaa"""

    def __getattribute__(self, item):
        print("设置对象的属性")
        return object.__getattribute__(self, item)

    def __getattr__(self, item):
        print("调用getattr方法啦")
        return "hahah ,什么也没有"
p = Person()
p.name = '张三'
print(p.name)
print(p.__dict__)
print(getattr(p,'name')) #getattr会去调用__getatrribute__这个方法,有属性则返回张三.
print(p.age)
print(getattr(p,'age'))#会去调用__getattribute__,没有这个属性,则会去调用__getattr__这个方法.

返回结果

设置对象的属性
张三
设置对象的属性
{'name': '张三'}
设置对象的属性 
张三     
设置对象的属性
调用getattr方法啦
hahah ,什么也没有
设置对象的属性
调用getattr方法啦
hahah ,什么也没有、”

综上:这个方法叫做属性访问拦截器也是原因的,就是不想按正常的返回属性值,你自己想特立独行,返回你自己想返回的东东,那么你可以自己重写该方法。
2、__setattr__方法,是在对属性值进行赋值的时候会自动去调用,该方法是去__ditc__这个对象字典中增加属性,所以如果是重写这个方法的话,一定要记得对__dict__这个字典增加对应的属性,否则,使用这个属性的时候,去__dict__字典中是查不到的。
#设置__setattr__方法

class Person(object):
    country = 'CHINA'

    def __init__(self,name):
        self.name = name   #对属性name进行赋值了,所以会去调用__setattri__

    def __setattr__(self, key, value):
        print("key:{} \t value:{}".format(key,value))
        self.__dict__[key] = value

p = Person('李四')
print(p.__dict__)
p.age = 18 ##对属性age进行赋值了,所以会去调用__setattr__
print(p.__dict__)
print(p.name) 

返回结果:

key:name	 value:李四
{'name': '李四'}
key:age	 value:18
{'name': '李四', 'age': 18}
李四

如果将__setattri__方法中的最后一行去掉:self.dict[key] = value,那么 print(p.name)会报错,上述的打印字典也会为{}
运行结果:

key:name	 value:李四
{}
key:age	 value:18
{}
Traceback (most recent call last):
  File "D:/自动化B/python_test/0921/test_9_21.py", line 31, in <module>
    print(p.name)
AttributeError: 'Person' object has no attribute 'name'

如果将p.age = 18的赋值改成setattr(p,‘age’,‘18’),也是一样会去调用__setattr__()这个方法.如下:

class Person(object):
    country = 'CHINA'

    def __init__(self,name):
        self.name = name   #对属性name进行赋值了,所以会去调用__setattri__

    def __setattr__(self, key, value):
        print("key:{} \t value:{}".format(key,value))
        self.__dict__[key] = value

p = Person('李四')
print(p.__dict__)
p.age = 18 ##对属性age进行赋值了,所以会去调用__setattr__
setattr(p,'sex','男')#对对象p添加了属性sex并进行赋值,此时会自动去调用__setattr__这个方法.
print(p.__dict__)
print(p.name)

运行结果:

key:name 	 value:李四
{'name': '李四'}
key:age 	 value:18
key:sex 	 value:#这一行就是去调用__setattr__返回的结果
{'name': '李四', 'age': 18, 'sex': '男'}
李四

对对象的属性进行赋值有以下几种情况:
①实例化一个对象时,p = Person(‘李四’),会自动去调用__init__方法,方法中self.name就是对对象的赋值,此时会自动去调用__setattr__这个方法
②在类外面,直接使用对象进行赋值时,p.age = 18 ,也会去调用.
③使用python的内置函数:setatrr(对象名,变量名,值),变量名需要加引号,这个时候也会去自动调用__setattr__这个方法.

综上:该方法是只要对对象的属性进行赋值,就会被调用,object中有内置该方法,用户感知不到,如果想在设置属性值的时候进行其他的输出,可以进行重写该方法,但是一定要注意对对象的字典进行更新属性值。

3、__delattr__这个属性,也是object内置的属性,在用户进行del 对象的属性时会被调用。

#delattr
class Person(object):

def __delattr__(self, item):
    print("删除属性")
    del self.__dict__[item]

p = Person()
p.name = ‘张三’
p.age = 18
print(p.dict)
del p.name #会去调用__delattr__这个方法
print(p.dict)
del p.age #会去调用__delattr__这个方法
print(p.dict)

运行结果:
{‘name’: ‘张三’, ‘age’: 18}
删除属性
{‘age’: 18}
删除属性
{}

如果不去重写这个方法,则会默认去调用object 这个父类的__delattr__这个方法,从字典列表中删除这个属性值的引用,如果重写这个方法,则会首先去自己类中查找这个方法进行调用,可以根据需要进行重写方法体。

总结:重写方法体的时候可能会遇到坑,内存溢出的情况,程序进入死循环:
①在__getattribute__方法中,不要使用self.属性名,这个会再次触发调用__getatrribute__方法。
②在__setattr__方法体中不要使用self.属性名去设置属性的值,也会使程序进入死循环。
③在__delattr__方法体中不要使用del self.属性名,因为del 会触发调用__delattr__这个方法。从而导致程序最终进入死循环,内存不断的消耗,最后机器宕机。

以上其实就是对象的变量的增删改的操作,类似列表,元组,字符串,字典等.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如梦@_@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值