🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

Python类与面向对象编程入门【新手指南】

要在电脑上通过命令提示符或 PowerShell 运行 Python,需要先下载并安装 Python。
如果你还没有安装,请参考Python安装与开发环境配置一文来完成安装。

刚踏入Web开发世界的朋友们,大家好!这次,我们将用最通俗易懂的方式,为大家讲解许多编程语言都在使用的重要思想——“面向对象编程(OOP)”,以及其在Python中的核心——“类”。不用害怕专业术语,读完这篇文章,你一定会恍然大悟:“原来是这么回事!”

本文最大的目标,就是想让大家体验到“代码成功运行的乐趣”。我们会把复杂的理论放一放,先从复制粘贴就能运行的代码入手,亲身感受面向对象编程的便利!


面向对象到底是什么?

一听到“面向对象”,是不是感觉有点难?但其实,这是我们日常生活中随处可见的一种思维方式。

最常用的一个比喻就是“饼干模具”“饼干”

在编程世界里,只要我们创建好“设计图”(类),就能用它高效、大量地生产出具体的“东西”(对象)。这就是面向对象的基本思想。在网站开发中,如果我们将“用户”、“博客文章”、“商品”等元素都作为对象来处理,那么再复杂的系统也能变得井然有序。


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`文件,然后在你的计算机终端(或命令提示符)中运行它。快来亲身体验“代码跑起来”的乐趣吧!

运行方法

  1. 复制下面的全部代码。
  2. 粘贴到文本编辑器(如VSCode)中,并保存为`user_manager.py`。
  3. 打开终端,切换到你保存文件的目录。
  4. 输入`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
状态: 禁用

感觉怎么样?通过使用类,用户信息和相关操作(如禁用)被清晰地组织在一起,是不是感觉代码的可读性大大提高了?


注意事项和常见错误

最后,我们来介绍几个新手在使用类时容易犯的错误。


下一步

了解了类和面向对象的基础之后,接下来让我们试试Python强大的标准库吧。在程序中处理日期和时间是一项非常常见的任务。

在下一篇文章中,我们将学习如何使用`datetime`模块来获取当前日期、进行日期计算等。

→ 如何使用 datetime 模块处理日期和时间