python之__getattribute__方法 || __getattr__方法 || __setattr__方法 ||__delattr__方法 || __dir__方法

前言

python语言的五个魔术方法,他们都与Python属性相关,涉及获取、删除和修改。

__getattribute__方法

源码如下:

实战演练:

①首先定义一个类并访问类的对象属性:

class User:

    def __init__(self, name, sex):
        self.name = name
        self.sex = sex


u1 = User(name='li', sex='male')
print(u1.name)

运行结果:

②接着在该类中加入 __getattribute__ 魔方方法。【访问对象属性就会交给该魔方方法处理】

class User:

    def __getattribute__(self, item):
        return '无论对象是否存在该属性,都会返回此值'

    def __init__(self, name, sex):
        self.name = name
        self.sex = sex


u1 = User(name='li', sex='male')
print(u1.name)
print(u1.age)

运行结果:【因为User类中的 __getattribute__ 魔方方法重写了基类object类的方法,所以此时的 __getattribute__  方法不在返回对象的属性,而是返回程序中重写后的内容】

 __getattribute__  魔方方法介绍

①触发时间:在访问对象成员属性的时候触发,无论对象的成员属性是否存在。

②作用:对属性进行一些处理。

③参数:

  • self为当前对象;
  • item是访问属性名称的字符串。

④返回值:对象的属性值。

【注意】

① __getattribute__ 方法的是返回值千万不能用 self.name ,否则获取对象属性时会无限递归下去,

例如:

class User:

    def __getattribute__(self, item):
        return self.name

    def __init__(self, name, sex):
        self.name = name
        self.sex = sex


u1 = User('li', 'male')
print(u1.name)

运行结果:

②可以使用 object.__getattribute__ 方法来访问对象成员属性。

例如:

class User:

    def __getattribute__(self, item):
        return object.__getattribute__(self, item)

    def __init__(self, name, sex):
        self.name = name
        self.sex = sex


u1 = User('li', 'male')
print(u1.name)

运行结果:

__getattr__方法

  • 触发时间:在访问不存在的对象属性的时候触发。
  • 作用:访问不存在的属性时候,不会报错。
  • 参数:self为当前对象,item是访问属性名称的字符串。
  • 返回值:属性值。

我们举个简单例子,就是用户可能会输出属性名称,那我们都统一返回name属性。

class User:

    def __getattr__(self, item):
        return self.name

    def __init__(self, name, sex):
        self.name = name
        self.sex = sex


u1 = User('li', 'male')
print(u1.na2me)

li

__setattr__方法

  • 触发时间:添加和修改对象属性的时候触发。
  • 作用:限制添加和修改对象属性的操作。
  • 参数:self为当前对象,key为设置对象属性名称, value为设置的值。
  • 返回值:无。

例如,我们让用户可以改name,不能改sex。

__delattr__方法

  • 触发时间:删除对象属性的时候触发。
  • 作用:限制添加和修改对象属性的操作。
  • 参数:self为当前对象,item为删除对象属性名称。
  • 返回值:无。

例如:我们可以让用户删除sex,但是不能删除name。

class User:

    def __delattr__(self, item):
        if item == 'sex':
            pass
        else:
            object.__delattr__(self, item)

    def __init__(self, name, sex):
        self.name = name
        self.sex = sex


u1 = User('li', 'male')
del u1.sex
print(u1.sex)
del u1.name
print(u1.name)

male
AttributeError: 'User' object has no attribute 'name'

__dir__方法以及Python __dict__与dir()区别

Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案。

__dir__方法详细查看此篇博客:https://www.cnblogs.com/hls-code/p/15262760.html

 __dict__dir()的区别:

  1. dir()是一个函数,返回的是list;
  2. __dict__是一个字典,键为属性名,值为属性值;
  3. dir()用来寻找一个对象的所有属性,包括__dict__中的属性,__dict__是dir()的子集;

dir()是Python提供的一个API函数,dir()函数会自动寻找一个对象的所有属性(包括从父类中继承的属性)。

​ 一个实例的__dict__属性仅仅是那个实例的实例属性的集合,并不包含该实例的所有有效属性。所以如果想获取一个对象所有有效属性,应使用dir()。

print dir(A)
'''
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'class_f', 'class_var', 'fun', 'level1', 'level2', 'name', 'num', 'static_f']
'''
a_dict = a.__dict__.keys()
A_dict = A.__dict__.keys()
object_dict = object.__dict__.keys()
print a_dict  
print A_dict  
print object_dict 
'''
['fun', 'level1', 'age', 'name']

['__module__', 'level2', 'num', 'static_f', '__dict__', '__weakref__', '__init__', 'class_f', 'class_var', 'fun', '__doc__']

['__setattr__', '__reduce_ex__', '__new__', '__reduce__', '__str__', '__format__', '__getattribute__', '__class__', '__delattr__', '__subclasshook__', '__repr__', '__hash__', '__sizeof__', '__doc__', '__init__']
'''

#因为每个类都有一个__doc__属性,所以需要去重,去重后然后比较
print set(dir(a)) == set(a_dict + A_dict + object_dict)  #True

 

https://www.cnblogs.com/zjchao/p/7894477.html

属性访问顺序

最后,属性访问的顺序如下:

  • __getattribute__
  • 数据描述符
  • 当前对象的属性
  • 类的属性
  • 非数据描述符
  • 父类的属性
  • __getattr__
posted @ 2021-09-15 17:07  习久性成  阅读(477)  评论(0编辑  收藏  举报