编程学习网 > 编程语言 > Python > Python中如何动态获取和设置对象的属性?
2025
06-28

Python中如何动态获取和设置对象的属性?


在Python这门语言里,动态获取和设置对象属性这事儿,简直就跟吃饭一样常见,说起来简单,里面其实也有不少门道。今天我就想聊聊这个话题,结合我这些年踩过的坑,带大家一起拆解一下这套机制到底是怎么回事,顺便说说我对它的一些看法。

你如果是初学Python,那八成先接触的是通过点号来访问属性,比如 obj.name 这样。这玩意儿语法糖看着顺眼、写着顺手。但问题来了,要是这个属性名是动态的、运行时才知道的,那你就得换个方式了,用内置的 getattr 和 setattr。就这两个函数,几乎撑起了Python对象系统一半的“魔法”。

说到这儿,有些兄弟可能就开始敷衍了:“不就 getattr(obj, 'name') 和 setattr(obj, 'name', value) 吗,这谁不会啊?”哎,这你就太小看Python了。动态设置和获取属性,可不光是API层面那么简单,它背后还牵扯到类、元类、属性查找顺序、魔法方法,甚至还能搞出一堆骚操作,比如动态代理、懒加载、权限控制、序列化钩子,等等。

咱们先说最基本的用途吧,最常见的场景无非就是处理一些字段名不固定的数据,比如从数据库拉出来的一堆dict,字段可能随环境而变,你要是一条条写属性访问,那还不累死?这时候直接循环 for k, v in data.items(): setattr(obj, k, v),一行解决,效率也高。

还有种情况,就是你想封装点底层逻辑,比如控制只读属性、做缓存啥的。举个例子,我之前做过一个配置系统,配置项很多,有些是常量,有些是动态算出来的,还有些需要从远程拉,最开始我是写了一堆 @property 配着 if 判断,结果代码又臭又长。后来我改成用 __getattr__ 和一个dict做延迟加载的map,结果代码缩了一半,还方便测试。原理也简单:__getattr__ 是在找不到属性时自动调用的“兜底方案”,你可以在里面写各种逻辑。

比如:

这样一来,配置项只在首次访问时加载,后面走缓存,性能提升不是一星半点。

再往深一点说,有时候你甚至可以用 __getattribute__ 来做一些“黑魔法”级别的操作。这个方法比 __getattr__ 更底层,它是所有属性访问都会走的,哪怕那个属性确实存在。你可以用它做权限控制、审计日志、接口代理,比如你想监控某个对象的所有属性访问情况,哪怕只是简单读取个值,也能被记录下来。

不过这玩意儿用不好就是灾难。之前我们组有个哥们就踩过坑,为了加个日志,把 __getattribute__ 改了,结果线上崩了两小时——因为他忘了所有内部访问比如 self.__dict__ 也会触发这个函数,死循环了……所以兄弟们,碰这个之前,一定要搞清楚属性查找流程是怎么走的。

除了读取,动态设置属性也很有用。比如做ORM系统的时候,一个模型类的字段名是数据库表结构定的,难不成你要在类里硬编码?像Django、SQLAlchemy这些框架,基本上都会在类创建时用 type 或元类动态添加属性和方法,实现类似 User.name 这种语法的。你要手动实现其实也不难,就靠 setattr 和 __dict__ 这俩东西。只不过得配合一点类的构造知识,不然你很容易乱套。

这还没完,hasattr 和 delattr 也常用,尤其是做反射类操作的时候,能让你的代码适配性更强。比如你在写一套插件框架,插件定义了一堆功能函数,你只知道函数名但不知道它是不是实现了,那你用 hasattr(plugin, 'run') 就能提前探测一波,做个容错机制。

还有个我自己特别爱用的技巧,就是“方法注入”。有时候我不想写继承,但又想给对象加点特定方法,就动态绑定:

这样你就可以在运行时给某个对象加上一个“方法”,而不是普通函数。这个在写DSL或者命令式脚本引擎的时候超级好用。

不过话又说回来,这些骚操作写起来爽,维护起来可不一定。我见过最离谱的是一个哥们写了个全靠 getattr + eval 的路由系统,整个项目就跟动态语言的AST解析似的,debug起来跟进迷宫一样。所以我觉得吧,动态属性访问确实强大,但你得适度用,别一上来就把它当成银弹。

最后还有一点就是反序列化相关。比如你拿到一个json,想把它变成Python对象,一般会用个类来封装,然后动态设置属性。你可以写个简单的封装器,把 json.loads() 的结果一股脑塞到对象里,连dict都不用显式访问:

虽然简陋,但能用,还方便拓展,很多项目初期就靠这个“贫民版ORM”活下来的。

总结一下吧,动态获取和设置属性在Python里是个老生常谈的问题,看着简单,其实能玩出不少花样。从最基础的 getattr/setattr 到魔法方法 __getattr____getattribute__,再到元类和反射操作,每一层都藏着设计上的权衡。

你说它灵活?是的,但灵活也意味着容易失控。所以我的建议是,只有在你需要动态行为、配置不固定、插件式架构或者做框架开发的时候,才去用这些高级玩法。平时写业务代码,老老实实点属性,有IDE提示才是王道。

说了这么多,不知道你们有没有踩过这方面的坑?或者有没有哪种奇技淫巧是我漏掉的?欢迎留言,我们一起挖一挖Python属性系统的更多可能。

以上就是“Python中如何动态获取和设置对象的属性?的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取