python魔法方法之__setattr__()

作者:机器学习入坑者 时间:2021-06-06 13:27:47 

前言:

python提供了诸多的魔法方法,其中__setattr__()方法主要用于类实例进行属性赋值,其定义在Object类官方提供的说明如下:

Called when an attribute assignment is attempted. 
This is called instead of the normal mechanism (i.e. store the value in the instance dictionary).
 name is the attribute name, value is the value to be assigned to it.

简单的说,__setattr__()在属性赋值时被调用,并且将值存储到实例字典中,这个字典应该是self的__dict__属性。即:在类实例的每个属性进行赋值时,都会首先调用__setattr__()方法,并在__setattr__()方法中将属性名和属性值添加到类实例的__dict__属性中。

python魔法方法之__setattr__()

1、实例属性管理__dict__

下面的测试代码中定义了三个实例属性,每个实例属性注册后都print()此时的__dict__

代码如下:

class AnotherFun:
    def __init__(self):
        self.name = "Liu"
        print(self.__dict__)
        self.age = 12
        print(self.__dict__)
        self.male = True
        print(self.__dict__)
another_fun = AnotherFun()

得到的结果显示出,每次实例属性赋值时,都会将属性名和对应值存储到__dict__字典中:

{'name': 'Liu'}
{'name': 'Liu', 'age': 12}
{'name': 'Liu', 'age': 12, 'male': True}

2、__setattr__()与__dict__

由于每次类实例进行属性赋值时都会调用__setattr__(),所以可以重载__setattr__()方法,来动态的观察每次实例属性赋值时__dict__()的变化。下面的Fun类重载了__setattr__()方法,并且将实例的属性和属性值作为__dict__的键-值对:

class Fun:
    def __init__(self):
        self.name = "Liu"
        self.age = 12
        self.male = True
        
    def __setattr__(self, key, value):
        print("*"*50)
        print("setting:{},  with:{}".format(key[], value))
        print("current __dict__ : {}".format(self.__dict__))
        # 属性注册
        self.__dict__[key] = value
fun = Fun()    

通过在__setattr__()中将属性名作为key,并将属性值作为value,添加到了__dict__中,得到的结果如下:

**************************************************
setting:name,  with:Liu
current __dict__ : {}
**************************************************
setting:age,  with:12
current __dict__ : {'name': 'Liu'}
**************************************************
setting:male,  with:True
current __dict__ : {'name': 'Liu', 'age': 12}

可以看出,__init__()中三个属性赋值时,每次都会调用一次__setattr__()函数。

3、重载__setattr__()必须谨慎

由于__setattr__()负责在__dict__中对属性进行注册,所以自己在重载时必须进行属性注册过程,下面是__setattr__()不进行属性注册的例子:

class NotFun:
    def __init__(self):
        self.name = "Liu"
        self.age = 12
        self.male = True
    
    def __setattr__(self, key, value):
        pass
not_fun = NotFun()
print(not_fun.name)

由于__setattr__中并没有将属性注册到__dict__中,所以not_fun对象并没有name属性,因此最后的print(not_fun.name)会报出属性不存在的错误:

AttributeError                            Traceback (most recent call last)
<ipython-input-21-6158d7aaef71> in <module>()
      8         pass
      9 not_fun = NotFun()
---> 10 print(not_fun.name)

AttributeError: 'NotFun' object has no attribute 'name'

所以,重载__setattr__时必须要考虑是否在__dict__中进行属性注册。

总结:

python的实例属性的定义、获取和管理可以通过__setattr__()和__dict__配合进行,当然还有对应的__getattr__()方法,本文暂时不做分析。__setattr__()方法在类的属性赋值时被调用,并通常需要把属性名和属性值存储到self的__dict__字典中。

来源:https://zhuanlan.zhihu.com/p/101004827

标签:python,魔法,方法,setattr,()
0
投稿

猜你喜欢

  • python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍

    2022-04-18 06:08:49
  • django model object序列化实例

    2022-07-03 14:55:24
  • 利用Anaconda完美解决Python 2与python 3的共存问题

    2022-05-16 17:51:43
  • 关于Python 3中print函数的换行详解

    2021-04-09 09:57:48
  • python提效小工具之统计xmind用例数量(源码)

    2021-11-26 21:42:44
  • 带你轻松了解 SQL Server数据库的组成

    2009-02-05 15:53:00
  • Python读取Json字典写入Excel表格的方法

    2021-06-20 06:33:58
  • Python使用tkinter库实现文本显示用户输入功能示例

    2023-09-21 11:00:17
  • 使用TensorFlow搭建一个全连接神经网络教程

    2023-01-10 10:59:20
  • Oracle分析函数用法详解

    2023-07-16 15:35:26
  • python机器学习理论与实战(六)支持向量机

    2023-10-18 22:59:53
  • python列表排序用 sort()和sorted()的区别

    2021-11-27 10:36:20
  • python神经网络Keras构建CNN网络训练

    2022-08-16 08:42:37
  • Python利用pyHook实现监听用户鼠标与键盘事件

    2021-09-04 19:59:59
  • python根据txt文本批量创建文件夹

    2021-12-18 21:24:52
  • python爬取酷狗音乐Top500榜单

    2023-01-26 03:09:17
  • Python中绑定与未绑定的类方法用法分析

    2021-08-06 22:56:54
  • 简单介绍Python中的struct模块

    2023-09-22 16:27:01
  • PHP CURL CURLOPT参数说明(curl_setopt)

    2023-11-14 19:06:44
  • 通过python+selenium3实现浏览器刷简书文章阅读量

    2022-11-09 09:04:37
  • asp之家 网络编程 m.aspxhome.com