__setattr__, __getattr__, __getattribute__, _ getitem_的用法和区别

一、 类实例属性的获取与设置 

转载自

转载自

1. __getattribute__

程序每次访问对象属性时,Python系统都会调用这个特殊的方法,即使属性字典里面已经有了该属性,也依然会触发__getattribute__。

__getattribute__方法下应该避免使用self.attr访问属性,否则会出现无限递归。如要要访问实例属性,应该直接通过super()来做。

2. __getattr__

如果某类定义了__getattr__,同时系统在该类对象的实例字典中又找不到待查询的属性,系统就会调用这个方法,这种行为非常适合无结构数据的按需访问。除非__getattribute__调用它或者出现AttributeError错误,否则__getattr__方法不会被调用。

3. __setattr__ 和 __delattr__

只要对实例属性赋值,无论是直接赋值,还是通过内置的setattr赋值,都会触发__setattr__方法。__setattr__下还有self.attr的赋值操作就会出现无限递归的调用__setattr__的情况。一般情况都还是继承。__setattr__ 和 __delattr__破解无限递归的方法有两种:

(1)我们去调用系统写好的基类,系统的总是最安全的!super()可以帮你找到所有函数的父类

def __setattr__(self,name,value):

    super().__setattr__(name,value)

(2)我们要用到一个对象的特殊属性:__dict__它的作用是以字典的属性显示出当前对象的所有属性以及对应的值!比如:{'b': 1}

def __setattr__(self,name,value):

    self.__dict__[name] = value
 

举例如下:

class B(object):
    def __init__(self):
        self.name = 'tom'

    # 同时有__getattribute__和__getattr__时,会先调用前者。
    # 只有该属性不存在或出现异常时才会调用后者
    def __getattribute__(self, name):
        print('Called __getattribute__(%s)' % name)
     # # _getattribute__方法下应该避免使用self.attr访问属性,否则会出现无限递归。
        #   return self.__dict__['name'] #导致无限递归,不能这样用!
        return super().__getattribute__(name)

    def __getattr__(self, name):
        print('Called __getattr__(%s)' % name)


class C:
    def __setattr__(self, name, value):
        print('Called __setattr__(%s, %r)' % (name, value))
        # _setattr__下还有self.attr的赋值操作就会出现无限递归的调用__setattr__的情况。一般情况都还是继承
        # 不过对于__setattr__,是能使用 self.__dict__[name] = value
        super().__setattr__(name, value)
        


b=B()
print(b.name)
print(b.fuck)
>>> b = B()
>>> b.a
Called __getattribute__(a)
Called __getattr__(a)

c = C()
c.a = 1
print(c.a)
setattr(c,'d',2)
print(c.__dict__)

 

二、 为实例添加“.”运算和“[]”运算符支持

转载自
这也是“_ getattribute_”与“_ getitem_”的最大差异,示例如下: 
1. “_ getattribute_”只适用于所有的“.”运算符; 
2. “_ getitem_”只适用于所有的“[]”运算符;

class Employee(object):

    def __init__(self, username, age):
        self.username = username
        self.age = age

    def __getattribute__(self, attr):
        return super(Employee, self).__getattribute__(attr)

    def __getitem__(self, attr):
        return super(Employee, self).__getattribute__(attr)

em = Employee('yiifaa', 32)
print em.username
#   现在支持“[]”运算符
print em['username']

通过实现“_ getitem_”回调接口,现在Employee可以支持“[]”运算符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值