2. 类与对象基础:如何定义一个类,如何创建对象,__init__构造方法详解,self参数的本质
好,咱们正式开始聊面向对象编程的核心——类与对象。
说实话,很多初学者学到这里就开始犯迷糊了。什么类啊对象啊,听着像哲学概念。其实没那么玄乎。我当年刚接触Python时,也觉得这东西抽象。直到我在项目中写了一个用户管理系统,才真正体会到:类就是模板,对象就是根据模板造出来的具体实例。
2.1 什么是类?什么是对象?
咱们先打个比方。
你想想看,类就像一张建筑设计图。图纸上画好了房子有几室几厅、门窗位置、水电走向。但图纸本身不是房子,你不能住进去。你得照着图纸去施工,盖出来的那一栋栋具体的房子,才是对象。
在Python里,class关键字就是用来画这张设计图的。而通过类创建出来的具体实例,就是对象。
一句话总结:
- 类:定义了一组属性和行为的模板
- 对象:根据类创建出来的具体实体,拥有自己的数据
2.2 如何定义一个类
定义类用class关键字,后面跟类名,再加一个冒号。类名一般用大驼峰命名法,比如User、OrderManager。
class Dog:
"""这是一个狗的类"""
pass
嗯,这里要注意:pass表示暂时什么都不做,占个位置。实际开发中,类里面会写属性和方法。
我个人习惯,定义一个类时,先想清楚这个类要封装什么数据、提供什么行为。比如一个Dog类,可能有名字、年龄这些属性,还有叫、跑这些方法。
2.3 如何创建对象
创建对象很简单——调用类名加括号就行。就像调用函数一样。
my_dog = Dog()
这行代码干了三件事:
- 在内存中分配一块空间
- 调用
__init__方法(如果有的话)初始化对象 - 返回对象的引用,赋值给
my_dog
说白了,my_dog就是一个指向真实对象的“遥控器”。你通过它来操作对象。
2.4 __init__构造方法详解
这个__init__方法,是Python里最常用的魔法方法之一。它的作用是在对象创建后,自动执行初始化操作。
我曾经在项目中踩过一个坑:忘记写__init__,结果每个对象创建后还得手动去设置属性,代码又臭又长。后来老老实实把初始化逻辑都放进__init__里,清爽多了。
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
my_dog = Dog("旺财", 3)
print(my_dog.name) # 输出:旺财
注意看:__init__的第一个参数永远是self,后面可以跟任意多个参数。创建对象时传入的参数,会直接传递给__init__。
小技巧:
__init__不是构造函数,真正的构造函数是__new__。__init__只是初始化方法。不过日常开发中,我们通常把__init__当作构造函数来用,也没毛病。
2.5 self参数的本质
很多新手看到self就头疼。我刚开始学的时候也纳闷:这玩意儿到底是啥?为什么每个方法都要写它?
其实self就是对象自身的引用。当你调用my_dog.bark()时,Python会自动把my_dog这个对象作为第一个参数传给bark方法。所以self指向的就是调用这个方法的对象本身。
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print(f"{self.name}在汪汪叫")
my_dog = Dog("旺财")
my_dog.bark() # 等价于 Dog.bark(my_dog)
你看,my_dog.bark()和Dog.bark(my_dog)效果完全一样。这就是self的本质——它让你在方法内部能访问到当前对象的数据。
避坑指南:
我曾经见过有人把self写成this或者其他名字。虽然语法上允许,但千万别这么干!所有Python程序员都默认用self,你换个名字只会让别人看不懂你的代码。
2.6 完整示例:一个简单的用户类
咱们把上面这些知识点串起来,写一个完整的例子。
class User:
"""用户类"""
def __init__(self, username, email):
self.username = username
self.email = email
self.is_active = True
def login(self):
print(f"用户 {self.username} 登录成功")
def logout(self):
print(f"用户 {self.username} 已退出")
# 创建两个用户对象
user1 = User("张三", "zhangsan@example.com")
user2 = User("李四", "lisi@example.com")
user1.login() # 输出:用户 张三 登录成功
user2.logout() # 输出:用户 李四 已退出
每个对象都有自己的username、email和is_active。互不干扰。这就是面向对象的好处——数据和操作绑定在一起,清晰又安全。
2.7 本章知识体系
下面这张图帮你理清类与对象的核心关系:
2.8 几个容易混淆的点
| 概念 | 说明 | 常见误区 |
|---|---|---|
| 类 vs 对象 | 类是模板,对象是实例 | 把类当对象用(静态方法除外) |
| 属性 vs 变量 | 属性属于对象,变量属于作用域 | 在方法里直接定义变量当属性用 |
| self 不是关键字 | 只是约定俗成的参数名 | 改成其他名字导致代码难读 |
| __init__ 不是必须的 | 没有时对象也能创建 | 以为每个类都必须写__init__ |
我的建议:
刚开始学的时候,每个类都写上__init__,哪怕里面只写一个pass。养成习惯后,你就不会忘记初始化逻辑了。
好了,类与对象的基础就聊到这儿。记住:类是图纸,对象是房子;__init__是装修队,self是门牌号。把这个比喻刻在脑子里,后面学继承、多态就轻松多了。