Python类与面向对象编程入门【新手指南】
要在电脑上通过命令提示符或 PowerShell 运行 Python,需要先下载并安装 Python。
如果你还没有安装,请参考Python安装与开发环境配置一文来完成安装。
刚踏入Web开发世界的朋友们,大家好!这次,我们将用最通俗易懂的方式,为大家讲解许多编程语言都在使用的重要思想——“面向对象编程(OOP)”,以及其在Python中的核心——“类”。不用害怕专业术语,读完这篇文章,你一定会恍然大悟:“原来是这么回事!”
本文最大的目标,就是想让大家体验到“代码成功运行的乐趣”。我们会把复杂的理论放一放,先从复制粘贴就能运行的代码入手,亲身感受面向对象编程的便利!
面向对象到底是什么?
一听到“面向对象”,是不是感觉有点难?但其实,这是我们日常生活中随处可见的一种思维方式。
最常用的一个比喻就是“饼干模具”和“饼干”。
- 类 (Class): 就像是“饼干模具”。它好比一张设计图,规定了饼干的形状、需要哪些材料(比如巧克力豆、奶油等)。
- 对象 (Object): 就像是用“饼干模具”做出来的每一块“饼干”实体。即使用同一个模具,有的可能加了不同的配料,有的可能烤得焦一点,每一块都有自己的个性。
在编程世界里,只要我们创建好“设计图”(类),就能用它高效、大量地生产出具体的“东西”(对象)。这就是面向对象的基本思想。在网站开发中,如果我们将“用户”、“博客文章”、“商品”等元素都作为对象来处理,那么再复杂的系统也能变得井然有序。
Python类的基础:来创建一张设计图吧
那么,我们这就来用Python创建一个叫做“类”的设计图吧。在这里,我们以狗(Dog)为主题进行讲解。
1. 最简单的类
首先,我们来定义一个内容为空的类。仅此而已,它就是一张合格的“设计图”了。
# 定义一个名为Dog的类(设计图)
class Dog:
pass # pass 意为“什么都不做”,在语法上需要一条语句但又无代码可写时使用。
# 从Dog类创建一个具体的狗对象(实例)
my_dog = Dog()
# 看看 my_dog 是什么
print(my_dog)
运行结果:
<__main__.Dog object at 0x10e28a2d0>
从运行结果可以看出,一个`Dog`类的对象被成功创建了。(`0x...`这部分会根据你的运行环境而变化)
2. 用 `__init__` 初始化方法赋予个性
接下来,就像给饼干加馅料一样,我们来给狗赋予一些具体信息(称为属性),比如“名字”和“品种”。为此,我们要使用一个特殊的方法(类内部的函数)——`__init__`。这是一个初始化方法,在对象被创建的那一刻会自动执行。
class Dog:
# 创建对象时自动调用的初始化方法
def __init__(self, name, breed):
# 以 self.变量名 的形式将数据保存到对象中
self.name = name
self.breed = breed
print(f"{self.name} ({self.breed}) 出生了!")
# 创建一只名叫“Pochi”的“柴犬”对象
dog1 = Dog("Pochi", "柴犬")
# 创建一只名叫“Hachi”的“秋田犬”对象
dog2 = Dog("Hachi", "秋田犬")
# 分别显示它们的名字和品种
print(f"第一只狗的名字: {dog1.name}")
print(f"第一只狗的品种: {dog1.breed}")
print(f"第二只狗的名字: {dog2.name}")
print(f"第二只狗的品种: {dog2.breed}")
`__init__`的第一个参数`self`是一个特殊的关键字,指向正在被创建的对象本身。你可以把它当成一个约定俗成的写法。通过`self.name = name`这样的形式,我们就可以把数据和对象绑定起来,意思是“这个对象自己的名字是xxx”。
运行结果:
Pochi (柴犬) 出生了!
Hachi (秋田犬) 出生了!
第一只狗的名字: Pochi
第一只狗的品种: 柴犬
第二只狗的名字: Hachi
第二只狗的品种: 秋田犬
仅仅通过`Dog("Pochi", "柴犬")`这样调用类,`__init__`方法就会被执行,并创建出带有各自信息的对象。我们可以用`.`(点)来访问对象所拥有的信息,例如`dog1.name`。
3. 用方法定义行为
对象不仅可以拥有数据(属性),还可以拥有“行为”(方法)。对于狗来说,我们可以给它添加一个“叫”的行为。
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
# 添加一个狗叫的行为(方法)
def bark(self):
return f"{self.name}: 汪汪!"
# 创建对象
my_dog = Dog("Koro", "杂交犬")
# 调用bark方法
greeting = my_dog.bark()
print(greeting)
只需在类中使用`def`定义一个函数即可。这时也要记得,第一个参数必须是`self`。通过`self`,我们可以访问该对象自身的名字(`self.name`)。
运行结果:
Koro: 汪汪!
进阶篇:通过“继承”复用设计图
面向对象的真正强大之处现在开始体现。利用一种叫做“继承”的机制,我们可以基于已有的类(设计图)轻松地创建出功能有增改的新类。
例如,我们可以在`Dog`类的基础上,创建一个新的“导盲犬(GuideDog)”类。导盲犬是犬的一种,所以它同样拥有“名字”和“品种”,也会“叫”。除此之外,它还有一个特殊的工作(方法),就是“帮助人类”。
#作为基础的父类(超类)
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
print(f"一只名叫{self.name}的狗诞生了,品种是{self.breed}。")
def bark(self):
return f"{self.name}: 汪!"
# 继承Dog类来创建一个新的子类
class GuideDog(Dog): # 在括号里写上父类的名字
def assist(self):
return f"{self.name}正在安全地引导人们。"
# 创建导盲犬对象
g_dog = GuideDog("Elle", "拉布拉多犬")
# 也可以使用父类(Dog)的方法
print(g_dog.bark())
# 子类(GuideDog)中添加的独有方法
print(g_dog.assist())
像`class GuideDog(Dog):`这样,在类名后的括号里写上想要继承的类名,继承就完成了。仅此一步,`GuideDog`就继承了`Dog`的所有属性(`name`, `breed`)和方法(`bark`)。这大大提高了代码的复用性,非常高效。
运行结果:
一只名叫Elle的狗诞生了,品种是拉布拉多犬。
Elle: 汪!
Elle正在安全地引导人们。
实践案例:管理博客文章的类
接下来,我们看一个更贴近Web开发实际的例子。我们将创建一个`BlogPost`类来管理博客文章。一篇文章有“标题”、“内容”和“作者”,我们再给它一个“显示文章”的功能。
import textwrap
class BlogPost:
def __init__(self, title, content, author):
self.title = title
self.content = content
self.author = author
# 一个能整洁地显示文章信息的方法
def display(self):
print("--------------------")
print(f"标题: {self.title}")
print(f"作者: {self.author}")
print("--- 正文 ---")
# 将长文本换行显示
print(textwrap.fill(self.content, width=40))
print("--------------------")
# 创建多个文章对象
post1 = BlogPost(
"Python类入门",
"面向对象编程是像组装零件一样构建程序的思想。类是设计图,而对象是实体。",
"Taro Yamada"
)
post2 = BlogPost(
"网页设计基础",
"好的设计不仅在于视觉上的美观,更将用户的易用性放在首位。留白和色彩搭配非常重要。",
"Hanako Sato"
)
# 显示文章
post1.display()
post2.display()
像这样,将每一篇文章都作为一个对象来处理,数据(如标题)和行为(显示功能)就被打包在一起,管理起来非常方便。
运行结果:
--------------------
标题: Python类入门
作者: Taro Yamada
--- 正文 ---
面向对象编程是像组装零件一样构建程序的思想。类是设计图,而对象是实体。
--------------------
--------------------
标题: 网页设计基础
作者: Hanako Sato
--- 正文 ---
好的设计不仅在于视觉上的美观,更将用户的易用性放在首位。留白和色彩搭
配非常重要。
--------------------
【动手体验!】完整的Python代码示例
久等了!在这里,我们将展示一个集成了以上所有内容的“用户管理程序”的完整代码。 你可以将这段代码直接保存为`.py`文件,然后在你的计算机终端(或命令提示符)中运行它。快来亲身体验“代码跑起来”的乐趣吧!
运行方法
- 复制下面的全部代码。
- 粘贴到文本编辑器(如VSCode)中,并保存为`user_manager.py`。
- 打开终端,切换到你保存文件的目录。
- 输入`python user_manager.py`并按回车键。
如果你的电脑还没有安装Python,请从python.org下载。
# user_manager.py
class User:
"""
一个表示网站用户信息的类
"""
def __init__(self, user_id, name, email):
self.user_id = user_id
self.name = name
self.email = email
self.is_active = True # 默认为活动用户
def get_profile(self):
"""
格式化并返回用户的个人资料信息
"""
status = "活动" if self.is_active else "禁用"
return f"ID: {self.user_id}\n姓名: {self.name}\n邮箱: {self.email}\n状态: {status}"
def deactivate(self):
"""
禁用用户
"""
self.is_active = False
print(f"用户“{self.name}”已被禁用。")
# 执行主程序的部分
if __name__ == "__main__":
# 创建多个用户对象
user1 = User("web-creator", "田中 太郎", "tanaka@example.com")
user2 = User("designer-sato", "佐藤 花子", "sato@example.com")
# 显示个人资料
print("--- 用户列表 ---")
print(user1.get_profile())
print("-" * 20)
print(user2.get_profile())
print("\n" + "=" * 20 + "\n")
# 尝试禁用一个用户
user2.deactivate()
print("\n--- 更改后的用户列表 ---")
print(user1.get_profile())
print("-" * 20)
print(user2.get_profile())
当你运行这段代码时,你的终端应该会显示如下内容:
运行结果示意:
--- 用户列表 ---
ID: web-creator
姓名: 田中 太郎
邮箱: tanaka@example.com
状态: 活动
--------------------
ID: designer-sato
姓名: 佐藤 花子
邮箱: sato@example.com
状态: 活动
====================
用户“佐藤 花子”已被禁用。
--- 更改后的用户列表 ---
ID: web-creator
姓名: 田中 太郎
邮箱: tanaka@example.com
状态: 活动
--------------------
ID: designer-sato
姓名: 佐藤 花子
邮箱: sato@example.com
状态: 禁用
感觉怎么样?通过使用类,用户信息和相关操作(如禁用)被清晰地组织在一起,是不是感觉代码的可读性大大提高了?
注意事项和常见错误
最后,我们来介绍几个新手在使用类时容易犯的错误。
- 忘记写`self`:在定义方法时,如果忘记将`self`作为第一个参数,或者在方法内部访问属性时忘记加上`self.`(例如写成了`name`而不是`self.name`),程序就会报错。请记住一个原则:“在类内部,凡事都要通过`self`”。
- `__init__`拼写错误:`__init__`的前后各有两个下划线。如果只写一个(如`_init_`),它就会被当作一个普通方法,而不会在对象创建时被自动调用。
- 实例化时忘记加`()`:如果像`my_dog = Dog`这样忘记了括号,那么你得到的不是一个对象,而是类本身被赋给了变量。请务必记得加上括号,如`my_dog = Dog()`。
下一步
了解了类和面向对象的基础之后,接下来让我们试试Python强大的标准库吧。在程序中处理日期和时间是一项非常常见的任务。
在下一篇文章中,我们将学习如何使用`datetime`模块来获取当前日期、进行日期计算等。
→ 如何使用 datetime 模块处理日期和时间