写 Python 面试题文章,说实话,讲到“如何遍历一个 object 的所有属性并打印出来”,我第一反应就是:这不是面向对象编程的入门题嘛?但是啊,别小看这玩意儿,真要你用 Python 写出来,能写出“面儿上看简单、里子有深度”的,还真得稍微掂量掂量。下面我就来聊聊这个看似简单,实则暗藏玄机的题目。
我们先看个最基本的例子:
是不是很简单?__dict__ 是 Python 对象的一个“祖传魔法属性”,它存储了实例的所有属性,返回的是一个字典。这种方式非常直接,适合大多数用例,效率高,结果清晰。但是!你以为面试官只想听你说这一句?那你就太天真了。
面试嘛,总是喜欢给你加点难度,比如说对象继承了父类的属性、用了 @property 装饰器、还有些奇奇怪怪的 __slots__ 优化……这时候你再想用 __dict__,对不起,不一定能全都拿到。
比如你加个继承:
打印出来啥?你只能看到 name、age 和 job,看不到 species。为啥?因为 __dict__ 只会管实例自己那一份,父类的就得你自己手动去拿。这个时候你要是真在项目里用了多层继承,靠 __dict__ 是不够的。
这时候怎么办?聪明的 Pythonic 方式来了,用 dir():
你会看到一大堆属性,包括内置的 __init__、__class__、__module__,还有你自己的字段。但问题又来了,这玩意儿太全了,全到有点“噪音大”,你想找的是用户自定义的属性,结果系统的也一股脑儿地扔出来。
这时候我们得筛一筛:
这样就稍微好点了,但依然不能解决你拿不到 @property 装饰的属性值的问题。再举个例子:
你 __dict__ 里根本就没有 name,但你访问却能访问到。因为 name 是个 property,是通过方法动态计算出来的,不存在 __dict__ 里。
这时候就得用 getattr 搭配 dir 来硬拿了:
这样能拿到大部分属性值,包括 property。但也要注意,如果某个属性是通过方法动态生成,可能会抛异常,比如里面依赖数据库连接啊、网络调用啊、或者索引超范围了,这时候就得 try-catch 套上了。这里推荐一定要 try-except,否则你在面试现场崩了一个属性,现场就尴尬了。
另外,还有一种写法稍微 Pythonic 一点的,是使用 vars(),其实它跟 __dict__ 差不多:
这东西本质上就是拿对象的 __dict__,所以适用范围和问题是一样的,但写起来稍微清爽点。
那你可能问了,这几个方式我都知道了,到底面试时候要怎么说才显得我水平高?
我教你一招“四步法”答题技巧(别被吓住,听我说完):
第一步,说最基本的:可以用 __dict__ 获取对象的属性字典,并打印。
第二步,补充局限性:但 __dict__ 不能拿到继承或 property 的属性。
第三步,提出改进方法:可以用 dir() 配合 getattr() 来更全面地遍历。
第四步,加点实际经验:比如处理 @property 或者异常属性,要用 try-except 防止程序挂掉。
举个终极答题例子(你面试时候可以照这个节奏来):
“我会优先用 __dict__ 或 vars() 来打印对象的属性,因为这种方式简单直接,适合快速调试。但它只能获取当前实例的属性,不能拿到继承自父类的字段或者被 @property 装饰的属性。所以在需要更完整的信息时,我会用 dir() 遍历属性名,再用 getattr() 去获取具体值,同时用 try-except 包住,防止某些属性在访问时抛出异常,比如依赖外部资源。这样能确保打印出所有可用的属性,同时代码也更健壮。”
是不是比“直接用 __dict__”高一个 level?面试官听到你这么答,起码知道你真用过,踩过坑,不是照书抄的。
其实很多时候,Python 的“动态”特性就是个双刃剑。用得好,你拿它飞天;用不好,线上的 bug 能让你怀疑人生。属性这个事儿,看着简单,背后你得了解数据结构、对象模型、访问控制、反射机制、异常处理……你不深入理解这些东西,永远只能写最表面的代码。
哦对了,还有个彩蛋要提一下,如果你项目里用了 __slots__ 优化(比如为了解决内存占用问题),那你连 __dict__ 都用不了。像这样:
p.__dict__ 会直接抛异常,因为 __dict__ 被禁用了,这时候只能靠 getattr。所以你还得考虑这些特殊情况,这才是一个成熟 Python 开发者该具备的思维。
所以这道题,说简单不简单,说复杂也不复杂,关键在你能不能把表面问题背后的细节掰开揉碎说清楚。如果你能从 __dict__ 一路说到 @property、__slots__、dir() 和 getattr(),再结合点实战经验和代码例子,那就不是“会”了,而是“吃透了”。
最后我想说的是,这种面试题就是在考察你对语言底层的理解深度。真正让你写个框架或者工具的时候,这些技巧都会变成你提升代码质量的利器。写 Python,不懂对象模型,就跟写 Java 不懂 JVM 一样,是走不远的。你们觉得呢?
扫码二维码 获取免费视频学习资料
- 本文固定链接: http://phpxs.com/post/13268/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料