Skip to content

面向对象编程入门

理解 df.method() 的秘密 —— 为什么数据科学需要 OOP


什么是面向对象编程(OOP)?

面向对象编程(Object-Oriented Programming, OOP) 是一种编程范式,将数据和操作数据的方法组织在一起。

为什么社科学生要学 OOP?

你已经在用 OOP 了!

python
import pandas as pd

df = pd.DataFrame({'age': [25, 30, 35]})
result = df.mean()  # df 是对象,mean() 是方法

核心概念

  • 对象(Object):数据 + 方法的集合
  • 类(Class):对象的模板/蓝图
  • 方法(Method):对象的函数

为什么需要 OOP?

场景:管理受访者信息

传统方式(字典)

python
respondent1 = {
    'id': 1001,
    'name': 'Alice',
    'age': 30,
    'income': 75000
}

# 计算税后收入(函数分离)
def calculate_net_income(respondent, tax_rate=0.25):
    return respondent['income'] * (1 - tax_rate)

net = calculate_net_income(respondent1)

OOP 方式(类)

python
class Respondent:
    def __init__(self, id, name, age, income):
        self.id = id
        self.name = name
        self.age = age
        self.income = income

    def calculate_net_income(self, tax_rate=0.25):
        """数据和方法在一起"""
        return self.income * (1 - tax_rate)

# 使用
resp1 = Respondent(1001, 'Alice', 30, 75000)
net = resp1.calculate_net_income()  # 更直观!

优势

  • 数据和方法绑定在一起
  • 代码更有组织性
  • 便于复用和维护

理解 Pandas 的 OOP

python
import pandas as pd

# DataFrame 是一个类
df = pd.DataFrame({'x': [1, 2, 3]})  # df 是 DataFrame 的实例(对象)

# 以下都是方法(对象的函数)
df.head()          # 查看前几行
df.describe()      # 描述性统计
df.mean()          # 平均值
df.to_csv('out.csv')  # 保存

# 以下是属性(对象的数据)
df.shape           # (3, 1)
df.columns         # Index(['x'])
df.dtypes          # 数据类型

对比 R

r
# R (更函数式)
df <- data.frame(x = c(1, 2, 3))
head(df)           # 函数调用
mean(df$x)         # 函数调用
write.csv(df, 'out.csv')
python
# Python (更面向对象)
df = pd.DataFrame({'x': [1, 2, 3]})
df.head()          # 方法调用
df['x'].mean()     # 方法调用
df.to_csv('out.csv')

实战:创建简单的类

示例 1:学生类

python
class Student:
    """学生类"""

    def __init__(self, name, age, major):
        """构造函数:创建对象时自动调用"""
        self.name = name
        self.age = age
        self.major = major
        self.courses = []

    def enroll(self, course):
        """添加课程"""
        self.courses.append(course)
        print(f"{self.name} 已注册 {course}")

    def display_info(self):
        """显示信息"""
        print(f"姓名: {self.name}")
        print(f"年龄: {self.age}")
        print(f"专业: {self.major}")
        print(f"课程: {', '.join(self.courses)}")

# 使用
alice = Student("Alice", 25, "Economics")
alice.enroll("Microeconomics")
alice.enroll("Econometrics")
alice.display_info()

示例 2:调查响应类

python
class SurveyResponse:
    """问卷响应类"""

    def __init__(self, respondent_id, age, gender, income):
        self.respondent_id = respondent_id
        self.age = age
        self.gender = gender
        self.income = income

    def is_valid(self):
        """验证数据"""
        return (
            18 <= self.age <= 100 and
            self.income >= 0 and
            self.gender in ['Male', 'Female', 'Other']
        )

    def income_category(self):
        """收入分类"""
        if self.income < 50000:
            return "低收入"
        elif self.income < 100000:
            return "中收入"
        else:
            return "高收入"

    def summary(self):
        """生成摘要"""
        return f"ID{self.respondent_id}: {self.gender}, {self.age}岁, {self.income_category()}"

# 使用
resp1 = SurveyResponse(1001, 30, 'Female', 75000)
print(resp1.is_valid())         # True
print(resp1.income_category())  # 中收入
print(resp1.summary())          # ID1001: Female, 30岁, 中收入

OOP 核心概念

1. 类与对象

python
# 类是模板
class Dog:
    def bark(self):
        return "Woof!"

# 对象是实例
dog1 = Dog()  # 创建对象
dog2 = Dog()  # 创建另一个对象

print(dog1.bark())  # Woof!
print(dog2.bark())  # Woof!

2. 属性与方法

python
class Respondent:
    def __init__(self, age, income):
        # 属性(数据)
        self.age = age
        self.income = income

    # 方法(函数)
    def is_high_earner(self):
        return self.income > 100000

resp = Respondent(30, 120000)
print(resp.age)              # 属性访问
print(resp.is_high_earner()) # 方法调用

3. self 参数

python
class Person:
    def __init__(self, name):
        self.name = name  # self 指向当前对象

    def greet(self):
        # self 让方法访问对象的属性
        return f"Hello, I'm {self.name}"

p1 = Person("Alice")
p2 = Person("Bob")

print(p1.greet())  # Hello, I'm Alice
print(p2.greet())  # Hello, I'm Bob

面向对象 vs 函数式

函数式风格

python
def create_respondent(id, age, income):
    return {'id': id, 'age': age, 'income': income}

def calculate_tax(respondent, rate):
    return respondent['income'] * rate

def is_valid(respondent):
    return respondent['age'] >= 18

resp = create_respondent(1001, 30, 75000)
tax = calculate_tax(resp, 0.25)
valid = is_valid(resp)

面向对象风格

python
class Respondent:
    def __init__(self, id, age, income):
        self.id = id
        self.age = age
        self.income = income

    def calculate_tax(self, rate=0.25):
        return self.income * rate

    def is_valid(self):
        return self.age >= 18

resp = Respondent(1001, 30, 75000)
tax = resp.calculate_tax()
valid = resp.is_valid()

何时用哪种?

  • 函数式:简单脚本、数据分析
  • OOP:大型项目、需要复用的组件

社科学生的 OOP

你不需要深入学习 OOP,但要理解:

  1. Pandas DataFrame 是对象
python
df.head()        # 调用方法
df.shape         # 访问属性
  1. Scikit-learn 模型是对象
python
from sklearn.linear_model import LinearRegression

model = LinearRegression()  # 创建对象
model.fit(X, y)             # 调用方法
predictions = model.predict(X_test)
  1. Statsmodels 也用 OOP
python
import statsmodels.formula.api as smf

model = smf.ols('income ~ education + age', data=df)
results = model.fit()
print(results.summary())

练习题

练习 1:创建课程类

python
# 创建 Course 类
# 属性: name, credits, students (列表)
# 方法:
#   - add_student(student_name)
#   - get_enrollment()  # 返回学生数
#   - display_roster()  # 显示所有学生

course = Course("Econometrics", 4)
course.add_student("Alice")
course.add_student("Bob")
print(course.get_enrollment())  # 2
course.display_roster()

练习 2:改写为类

python
# 将以下函数式代码改为 OOP 风格

def create_survey(name, year):
    return {'name': name, 'year': year, 'responses': []}

def add_response(survey, response):
    survey['responses'].append(response)

def get_response_count(survey):
    return len(survey['responses'])

# 改写为 Survey 类

下一步

在下一节中,我们将学习 类与对象的详细用法

继续!

基于 MIT 许可证发布。内容版权归作者所有。