Sitelet https://www.datacamp.com/zh/tutorial/python-oop-tutorial
跳至内容

Python 面向对象编程:完整指南

逐步讲解 Python 面向对象编程基础:类、对象、属性和方法,并配有代码示例。
已更新 2026年10月6日  · 12分钟 阅读

使用 AI 探索

ChatGPTClaudePerplexity

面向对象编程(OOP)是广泛用于编写应用程序的思想。作为一名数据科学家,您应当能够编写应用程序来处理数据,以及完成更多相关任务。

在本教程中,我将讲解 Python 中面向对象编程的基础知识。您将学习如何创建类并实例化对象,如何定义方法并向其传递参数,以及如何为类添加属性。

要点速览

  • OOP 围绕类(蓝图)和对象(蓝图的实例)组织代码

  • 使用 class 关键字定义类,并在 __init__(self) 中初始化属性

  • 实例方法通过 self 访问对象数据,使用点号调用:my_object.method()

  • Python 支持 OOP 的四大支柱:封装、继承、多态和抽象

  • OOP 促进代码复用,可从单个类模板创建多个对象

什么是 OOP?

面向对象编程(OOP)基于命令式编程范式,通过语句改变程序状态。命令式意味着它侧重于描述程序应如何运行。命令式编程语言的示例包括 C、C++、Java、Go、Ruby 和 Python。

这与声明式编程相对,后者关注程序应该完成什么,而不指定如何完成(例如 SQL、XQuery)。有关范式对比,请参阅我们的函数式编程与 OOP 对照指南。

OOP 使用对象和类的概念。类可被视为对象的“蓝图”。它们可以拥有各自的

  • 属性:所具备的特征
  • 方法:可以执行的动作

与其他设计模式相比,OOP 有一些关键优势。开发通常更快、更省成本,模块化方法也使软件更易维护。进而,这会带来更高质量的软件,同时也便于通过新方法和新属性进行扩展。

不过,学习曲线会更长。核心概念需要在前期投入更多精力才能充分理解。从计算层面看,OOP 软件更慢,占用更多内存,因为需要编写更多代码行。

OOP 的四大支柱

除了类和方法,OOP 还建立在四大支柱之上,我之前仅作了简单提及。每一项都值得深入探讨,这里先给出快速概览,并附上相应教程链接。

支柱含义了解更多
封装将数据与方法打包在一起,并用命名约定控制访问(_private、__name_mangled)Python 中的封装
继承创建子类以复用并扩展父类行为Python 继承
多态不同的类共享同一接口,从而使代码可与对象互换协作Python OOP 课程
抽象使用抽象基类以简洁接口隐藏复杂性Python 抽象类

OOP 示例

一个类的示例是 Dog。别把它当作某只具体的狗,或您的狗。我们是在一般层面描述狗是什么、能做什么。狗通常有 name 和 age;这些是实例属性。狗还会 bark;这是一个方法。

当您谈到一只具体的狗,在编程中就对应一个对象:对象是类的实例化。这是面向对象编程的基本原理。例如,我的狗 Ozzy 属于 Dog 类。他的属性是 name = 'Ozzy' 和 age = '2'。另一只狗会有不同的属性。

Python 中的 OOP

Python 是学习和实践 OOP 最受欢迎的语言之一。下面我将介绍为何 Python 适合面向对象代码,并演示核心语法。

Python 是面向对象的吗?

Python 是一门很好且支持 OOP 的编程语言。您将用它来定义带有属性和方法的类,然后对其进行调用。

与 Java、C++ 或 R 等其他编程语言相比,Python 的关键优势在于其动态特性和高级数据类型。这意味着程序员无需声明变量和参数类型,使得开发更快、代码也比 Java 或 C++ 更易读。

如果您是 Python 新手,请务必查看我们的Python 入门课程。

如何创建类

要在 Python 中定义类,您可以使用class 关键字,后跟类名和冒号。

类内部通常用 def 定义一个 __init__ 方法(一个双下划线方法)。这是一个初始化器,您之后可用它来实例化对象。它类似于 Java 中的构造函数。

当您创建新对象时,__init__ 会自动调用。它接受一个参数:self,指向对象自身。

目前方法体内使用 pass 关键字,因为 Python 期望您在那里写点什么。请记得使用正确的缩进!

class Dog:

    def __init__(self):
        pass

注意:Python 中的 self 相当于 C++ 或 Java 中的 this。

在这个例子里,您已有一个(几乎是空的)Dog 类,但还没有对象。我们来创建一个!

开始免费学习 Python

实例化对象

要实例化一个对象,输入类名,后跟一对括号。您可以将其赋给变量,以便跟踪该对象。

ozzy = Dog()

然后打印它:

print(ozzy)
<__main__.Dog object at 0x111f47278>

为类添加属性

打印出 ozzy 后,很明显这个对象是一只狗。但您还没有添加任何属性。我们通过改写为 Dog 类添加名字和年龄:

class Dog:

    def __init__(self, name, age):  
        self.name = name
        self.age = age

您可以看到,该函数现在在 self 之后接收两个参数:name 和 age。它们分别被赋给 self.name 和 self.age。现在您可以创建一个带名字和年龄的新 ozzy 对象:

ozzy = Dog("Ozzy", 2)

要在 Python 中访问对象的属性,可以使用点号语法。即输入对象名,后跟一个点和属性名:

print(ozzy.name)

print(ozzy.age)
Ozzy
2

也可以把它组合成一句更完整的话:

print(ozzy.name + " is " + str(ozzy.age) + " year(s) old.")
Ozzy is 2 year(s) old.

这里使用了 str() 函数,将整数类型的 age 属性转换为字符串,以便在 print() 函数中使用。

在类中定义方法

现在您有了一个 Dog 类,它确实有名字和年龄,您也可以跟踪它们,但它实际上还不会做什么。这时就需要实例方法。您可以重写该类,加入一个 bark() 方法。注意再次使用了 def 关键字,以及 self 参数。

class Dog:

    def __init__(self, name, age):  
        self.name = name
        self.age = age

    def bark(self):
        print("bark bark!")

现在可以在实例化新的 ozzy 对象后,使用点号调用 bark 方法。该方法会在屏幕上打印 "bark bark!"。注意 .bark() 中的括号。调用方法时总是需要括号。本例中是空的,因为 bark() 方法不接收任何参数。

ozzy = Dog("Ozzy", 2)

ozzy.bark()
bark bark!

还记得之前如何打印 ozzy 吗?下面的代码将该功能实现到了 Dog 类中的 doginfo() 方法里。然后您实例化一些具有不同属性的对象并调用它们的方法。

class Dog:

    def __init__(self, name, age):  
        self.name = name
        self.age = age

    def bark(self):
        print("bark bark!")

    def doginfo(self):
        print(self.name + " is " + str(self.age) + " year(s) old.")

ozzy = Dog("Ozzy", 2)
skippy = Dog("Skippy", 12)
filou = Dog("Filou", 8)

ozzy.doginfo()
skippy.doginfo()
filou.doginfo()
Ozzy is 2 year(s) old.
Skippy is 12 year(s) old.
Filou is 8 year(s) old.

如您所见,您可以用点号在对象上调用 doginfo() 方法。返回的结果现在取决于您正在对哪个 Dog 对象调用该方法。

由于狗会变老,最好能相应地调整它们的年龄。Ozzy 刚过 3 岁生日,我们来修改它的年龄。

ozzy.age = 3

print(ozzy.age)
3

只需为属性赋予一个新值即可。您也可以在 Dog 类中实现一个 birthday() 方法:

class Dog:

    def __init__(self, name, age):  
        self.name = name
        self.age = age

    def bark(self):
        print("bark bark!")

    def doginfo(self):
        print(self.name + " is " + str(self.age) + " year(s) old.")

    def birthday(self):
        self.age +=1

ozzy = Dog("Ozzy", 2)

print(ozzy.age)
2
ozzy.birthday()

print(ozzy.age)
3

现在,您无需手动修改狗的年龄。每逢生日,直接调用 birthday() 方法即可。

向方法传递参数

您可能希望让我们的狗有个伙伴。由于不是所有的狗都那么合群,因此这应是可选的。

看看下面的 setBuddy() 方法。它像往常一样接收 self,并接收 buddy 作为参数。这里,buddy 将是另一个 Dog 对象。将 self.buddy 属性设为 buddy,并将 buddy.buddy 属性设为 self。

这意味着关系是互相的:您是您伙伴的伙伴。在这里,Filou 将成为 Ozzy 的伙伴,这也意味着 Ozzy 会自动成为 Filou 的伙伴。

您也可以不定义方法,改为手动设置这些属性,但那样每次设置伙伴都要多写一行代码。

注意在 Python 中,您无需指定参数类型。如果这是 Java,就需要这样做。

class Dog:

    def __init__(self, name, age):  
        self.name = name
        self.age = age

    def bark(self):
        print("bark bark!")

    def doginfo(self):
        print(self.name + " is " + str(self.age) + " year(s) old.")

    def birthday(self):
        self.age +=1

    def setBuddy(self, buddy):
        self.buddy = buddy
        buddy.buddy = self

现在您可以用点号调用该方法,并向其传入另一个 Dog 对象。在本例中,Ozzy 的伙伴将是 Filou:

ozzy = Dog("Ozzy", 2)
filou = Dog("Filou", 8)

ozzy.setBuddy(filou)

如果您现在想获取有关 Ozzy 的伙伴的一些信息,可以使用两次点号:第一次引用 Ozzy 的伙伴,第二次引用其属性。

print(ozzy.buddy.name)
print(ozzy.buddy.age)
Filou
8

注意,对 Filou 也可以这样做。

print(filou.buddy.name)
print(filou.buddy.age)
Ozzy
2

还可以调用伙伴的方法。传递给 doginfo() 的 self 参数现在是 ozzy.buddy,也就是 filou。

ozzy.buddy.doginfo()
Filou is 8 year(s) old.

Python OOP 示例

一个可能用到 Python 面向对象编程的示例是我们的Python 金融:算法交易教程。在其中,我们讲解如何为股票投资组合设置交易策略。

该交易策略基于股票价格的移动平均。如果满足 signals['short_mavg'][short_window:] > signals['long_mavg'][short_window:],则会产生一个信号。该信号是对股票未来价格变动的预测。

在下面的代码中,您会看到先进行初始化,然后计算移动平均并生成信号。由于这不是面向对象的代码,它就是一大段一次性执行的逻辑。

请注意,我们在示例中使用了 aapl,即苹果公司的股票代码。如果您想对另一只股票进行同样的操作,就必须重写代码。

# Initialize
short_window = 40
long_window = 100
signals = pd.DataFrame(index=aapl.index)
signals['signal'] = 0.0

# Create short simple moving average over the short window
signals['short_mavg'] = aapl['Close'].rolling(window=short_window, min_periods=1, center=False).mean()

# Create long simple moving average over the long window
signals['long_mavg'] = aapl['Close'].rolling(window=long_window, min_periods=1, center=False).mean()

# Create signals
signals['signal'][short_window:] = np.where(signals['short_mavg'][short_window:] > signals['long_mavg'][short_window:], 1.0, 0.0)   

# Generate trading orders
signals['positions'] = signals['signal'].diff()

# Print `signals`
print(signals)

在面向对象的方法中,您只需把初始化和信号生成代码写一次。

然后,您可以为每只需要计算策略的股票创建一个新对象,并在其上调用 generate_signals() 方法。请注意,OOP 代码与上面的代码非常相似,只是多了 self。

class MovingAverage():

    def __init__(self, symbol, bars, short_window, long_window):
        self.symbol = symbol
        self.bars = bars
        self.short_window = short_window
        self.long_window = long_window

    def generate_signals(self):
        signals = pd.DataFrame(index=self.bars.index)
        signals['signal'] = 0.0

        signals['short_mavg'] = self.bars['Close'].rolling(window=self.short_window, min_periods=1, center=False).mean()
        signals['long_mavg'] = bars['Close'].rolling(window=self.long_window, min_periods=1, center=False).mean()

        signals['signal'][self.short_window:] = np.where(signals['short_mavg'][self.short_window:] > signals['long_mavg'][self.short_window:], 1.0, 0.0)   

        signals['positions'] = signals['signal'].diff()   

        return signals

现在,您只需用想要的参数实例化一个对象并为其生成信号即可。

apple = MovingAverage('aapl', aapl, 40, 100)
print(apple.generate_signals())

对另一只股票进行同样操作就非常容易了。只需用不同的股票代码实例化一个新对象即可。

microsoft = MovingAverage('msft', msft, 40, 100)
print(microsoft.generate_signals())

结语

我们已经介绍了 Python 中的一些主要 OOP 概念。您现在知道如何声明类和方法、实例化对象、设置其属性以及调用实例方法。这些技能将在您未来的数据科学职业生涯中大有裨益。

若想以更现代的方式定义类,请查看Python 数据类,它能减少样板代码。如果您想进一步扩展继续使用 Python 所需的关键概念,请务必查看我们的Python 进阶课程。

随着程序规模扩大,使用 OOP 的代码复杂度也会增长。您会有不同的类、子类、对象、继承、实例方法等。对于复杂的继承场景,请了解多重继承与 super()。

Python OOP 常见问答

What is object-oriented programming (OOP)?

面向对象编程是一种以“对象”为核心的编程范式,对象可包含数据以及用于操作这些数据的代码。在 OOP 中,对象由称为“类”的模板创建,类定义了所创建对象的属性和行为。OOP 使您能够创建可重用代码,并更贴近地建模现实世界概念,因此被广泛用于各类软件项目。

What are classes and objects in Python?

在 Python 中,类是用于创建对象的模板。它定义了由其创建的对象的属性和行为。对象是类的一个实例,通过像调用函数一样调用类来创建。对象包含类定义的数据和行为,并具有唯一的身份标识。

How do I define a class in Python?

要在 Python 中定义类,使用 class 关键字,后跟类名和冒号。类定义使用缩进,缩进块中包含属于该类的属性和方法(函数)。

How do I create an object from a class in Python?

要从类创建对象,在 Python 中像调用函数那样调用该类,并将任何必要的参数传递给类的构造函数(__init__ 方法)。

What are the four pillars of OOP in Python?

面向对象编程的四大支柱是:封装(将数据与方法打包并限制访问)、继承(允许类从父类继承属性和方法)、多态(使不同类型的对象可被统一对待)、以及抽象(隐藏复杂实现,仅暴露必要特性)。

What is the difference between a class attribute and an instance attribute?

类属性由该类的所有实例共享,直接在类体中定义。实例属性是对象独有的,在 __init__ 方法内使用 self 定义。例如,所有狗都可以共享一个 species 类属性,但每只狗都有自己的 name 实例属性。

主题
Python
数据科学