写程序这些年,见过不少人在“对象”这个概念上绕圈子。你说它抽象吧,其实每个程序里到处都是对象;你说它具体吧,真让你解释“对象到底是什么”,很多人又说不利索。“04-对象”这个标题听着简单,背后牵扯出来的东西却一点都不少——类与对象的关系、对象操作的各种细节、框架里的对象生命周期、系统层面对象资源的处理……热搜词里那些“对象数组去重”“获取对象属性名”“对象作为方法参数”“Django删除对象”之类的问题,全是实际操作中高频出现的坑。
这篇文章我打算从几个实际场景切入,把对象相关的核心知识点串一遍,写的都是我在具体项目里遇到过、排查过、解决过的问题。适合正好学到“类和对象”这一章的同学,也适合工作两三年但对象细节没完全抠明白的人。保证你看完能直接用到代码里,而不是读完只会背概念。
1. 对象到底是什么:先搞懂类与对象的关系
1.1 类与对象的关系,说白了就是图纸和房子
很多教材一上来就甩定义:“类是对象的抽象,对象是类的实例”。这说法没错,但对初学者来说,听完跟没听一样。我更喜欢用图纸和房子来打比方:类就是一张建筑图纸,图纸上规定了房子要有几个房间、几个窗户、用什么材料;对象就是照着这张图纸实际盖出来的那一栋房子。图纸可以反复使用,盖出无数栋房子;每栋房子的结构和设计一致,但住进去的人不同、里面的家具不同,它们各自独立、互不干扰。
放到代码里看就特别直观:
python复制class Dog:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
def bark(self):
print(f"{self.name} is barking")
# 创建两个对象
dog1 = Dog("旺财", 3)
dog2 = Dog("来福", 5)
print(dog1.name) # 旺财
print(dog2.name) # 来福
Dog是类,dog1和dog2是对象。注意,类的属性(name、age)不会因为某个对象改变了而影响另一个对象,每个对象都维护自己独立的内存空间。这一点在实际开发里特别重要,很多人踩过“a对象改了值,b对象也跟着变”的坑,多半是没分清哪些是实例属性、哪些是类属性。
1.2 为什么非要搞出个对象:数据和行为打包
如果你只用Python写脚本,几百行的业务逻辑,用函数也能干完。但一旦项目规模上来了,你就会发现函数式写法有一个很大的问题:数据散落在各个地方,操作这些数据的函数也散落在各个地方,改需求的时候你根本不知道哪个函数动了哪块数据。
对象解决的核心问题,就是把数据和操作数据的方法打包在一起。比如一个用户对象,它内部有用户名、邮箱、手机号这些属性,也有登录、登出、修改密码这些方法。外部调用者不需要关心用户的内部数据结构怎么存、密码怎么加密,只需要调用对应方法就行。
java复制public class User {
private String username;
private String email;
private String passwordHash;
public boolean login(String password) {
// 内部校验逻辑,外部不需要知道细节
return PasswordUtil.verify(password, this.passwordHash);
}
public void changePassword(String oldPwd, String newPwd) {
if (login(oldPwd)) {
this.passwordHash = PasswordUtil.hash(newPwd);
}
}
}
这就是封装。外部不用管passwordHash是什么算法生成的,只要调用login方法就行。你后续想换加密算法,改的是User类内部,外部代码一行都不用动。这就是对象设计带来的第一个红利:可维护性。第二个红利是复用性——同一个User类,在登录接口、管理后台、用户中心都能用,不用到处复制逻辑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 高频对象操作与细节解析:空判断、数组去重、属性获取
2.1 判断对象为空:每个语言都有自己的坑
热搜词里“判断对象为空”出现的频率非常高。但“对象为空”这五个字在不同语言里含义完全不一样,甚至在同一语言里也有好几种“空”。以JavaScript为例,新手最容易犯的错误就是直接拿对象跟null比:
javascript复制const obj = {};
if (obj === null) {
// 永远不会执行,因为obj是空对象,不是null
}
实际上,判断JS对象是否为空有三种常见思路:
Object.keys(obj).length === 0:判断自身可枚举属性数量JSON.stringify(obj) === '{}':序列化后比较Object.getOwnPropertyNames(obj).length === 0:包含不可枚举属性
但这三种也有区别。Object.keys只看自身可枚举属性,如果对象有不可枚举属性,它是检测不
