python中的getattribute 、getattr、setattr方法详解

 更新时间:2023年11月03日 10:14:25   作者:惊瑟  
这篇文章主要介绍了python中的getattribute 、getattr、setattr方法详解,python类中默认有一些特殊方法,这篇文章记录一下特殊方法的功能及用法,需要的朋友可以参考下

一、__getattribute__()

顾名思义,当访问object的属性会调用该方法,可以测试:

class A(object):

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

    def __getattribute__(self, attr):
        print("__getattribute__ is called")
        try:
            return super().__getattribute__(attr)
        except AttributeError:
            print(f'have no attr of {attr}')
            
if __name__ == '__main__':
    a = A('jyz',200)
    print(a.name)
    print(a.age)
		print(a.gender)

输出:

__getattribute__ is called
jyz
__getattribute__ is called
200
__getattribute__ is called
have no attr of gender
None

可以看出,当我们通过object.attrname的形式访问实例属性时,实际上我们是通过__getattribute__得到了该属性,是不是联想到了OOP中封装的思想?别急,下面会看到更多的oop设计思想。值得一提的是,在重写__getattribute__()方法时,一定要知道你在做什么,否则可能导致无法正确访问实例对象。另外,官方文档建议始终使用基类方法来设置属性,否则会陷入无限递归,最终栈溢出:

在这里插入图片描述

比如可以尝试:

class A(object):

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

    def __getattribute__(self, attr):
       return self.name
       
if __name__ == '__main__':
    a = A('jyz',200)
    print(a.name)

输出:

  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded

究其原因,是因为当使用self.name访问属性时会调用__getattribute__,而__getattribute__又要访问self.name,因此会无限递归下去。正确的做法是使用基类方法,对于该例子由于继承的是基类,因此使用super().__getattribute__(attr)或object.__getattribute__(self,attr)均可。

二、__setattr__()

实例初始化过程中,为实例属性赋值时会调用该方法。

class A(object):

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

    def __getattribute__(self, attr):
        print("__getattribute__ is called")
        try:
            return super().__getattribute__(attr)
        except AttributeError:
            print(f'have no attr of {attr}')

    def __setattr__(self, key, value):
        print(f"__setattr__() is called, key is {key}")
        object.__setattr__(self, key, value)

输出:

__setattr__() is called, key is name
__setattr__() is called, key is age

与__getattribute__同理,在__setattr__中也尽量使用基类的该方法来设置一些属性,否则可能发生无限递归。

三、__getattr__()

从字面意思理解跟__getattribute__差不多,事实上,该方法是__getattribute__的补充,当访问某些属性不存在,或**__getattribute__显示地抛出AttributeError**,会自动转到该方法做进一步处理。

在这里插入图片描述

可以测试:

class A(object):

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

    def __getattr__(self, attr):
        print(f"__getattr__() is called,but {attr} is not exist!")
   
if __name__ == '__main__':
    a = A('jyz',200)
    print(a.gender)

输出:

__getattr__() is called,but gender is not exist!
None

测试通过主动抛出异常的方式触发__getattr__():

class A(object):

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

    def __getattribute__(self, attr):
        if attr not  in ['name','age']:
            raise AttributeError
        else:
            return object.__getattribute__(self, attr)

    def __getattr__(self, attr):
        print(f"__getattr__() is called,but {attr} is not exist!")

if __name__ == '__main__':
    a = A('jyz',200)
    print(a.name)
    print(a.gender)
    

输出:

jyz
__getattr__() is called,but gender is not exist!
None

可以看到,上面两种方式都可以触发,__getattr__()。

到此这篇关于python中的getattribute 、getattr、setattr方法详解的文章就介绍到这了,更多相关getattribute 、getattr、setattr方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python创建进程fork用法

    python创建进程fork用法

    这篇文章主要介绍了python创建进程fork用法,实例分析了Python使用fork创建进程的使用方法,需要的朋友可以参考下
    2015-06-06
  • python图像常规操作

    python图像常规操作

    这篇文章主要介绍了python图像常规操作,比较全面,涉及读取和存储,生成缩略图,调整尺寸与旋转,绘制图像轮廓等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • 最小二乘法及其python实现详解

    最小二乘法及其python实现详解

    今天小编就为大家分享一篇最小二乘法及其python实现详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • 解决Python pandas plot输出图形中显示中文乱码问题

    解决Python pandas plot输出图形中显示中文乱码问题

    今天小编就为大家分享一篇解决Python pandas plot输出图形中显示中文乱码问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • 详解Python中三元运算符的使用

    详解Python中三元运算符的使用

    条件表达式(有时称为“三元运算符”)在所有Python操作中优先级最低,三元运算符根据条件为真或假来计算某些东西,下面就跟随小编一起来看看Python中三元运算符的具体使用吧
    2023-09-09
  • Python入门教程(七)Python数字类型

    Python入门教程(七)Python数字类型

    这篇文章主要介绍了Python入门教程(七)Python数字类型,Python是一门非常强大好用的语言,也有着易上手的特性,本文为入门教程,需要的朋友可以参考下
    2023-04-04
  • 从基础到高级详解DataFrame中时间序列操作的核心方法

    从基础到高级详解DataFrame中时间序列操作的核心方法

    时间序列数据是数据分析中最常见的类型之一,本文将系统介绍DataFrame中时间序列操作的核心方法,希望可以帮助大家掌握时间数据处理的全流程
    2026-02-02
  • 如何利用Python识别图片中的文字

    如何利用Python识别图片中的文字

    这篇文章主要给大家介绍了关于如何利用Python识别图片中文字的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Python具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-05-05
  • Python使用Tkinter编写串口通信调试工具

    Python使用Tkinter编写串口通信调试工具

    串口调试助手是一款基于Python和Tkinter开发的串口通信调试工具, 专为工程师和开发者设计,下面为大家详细介绍了如何使用Python实现串口通信调试工具,希望对大家有所帮助
    2026-01-01
  • 十个Python程序员易犯的错误

    十个Python程序员易犯的错误

    不管是在学习还是工作过程中,人都会犯错。虽然Python的语法简单、灵活,但也一样存在一些不小的坑,一不小心,初学者和资深Python程序员都有可能会栽跟头。本文为大家分享了10大常见错误,需要的朋友可以参考下
    2015-12-12

最新评论