day-025-面向对象-上

Day 25:面向对象(上)------类与对象

函数是"把代码打包",面向对象是"把数据和操作数据的函数打包在一起"。今天学面向对象编程(OOP)的核心概念:类(class)和对象(object)。


一、为什么要面向对象?

假设你要管理很多学生的信息:

python 复制代码
# 面向过程的写法:数据和操作分离
student1_name = "小明"
student1_score = 85

student2_name = "小红"
student2_score = 92

def print_student(name, score):
    print(f"{name}: {score}分")

print_student(student1_name, student1_score)

如果还要加年龄、城市、课程列表......变量越来越多,很容易搞混。

面向对象把数据和行为绑定在一起:

python 复制代码
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def print_info(self):
        print(f"{self.name}: {self.score}分")

# 创建对象(实例化)
s1 = Student("小明", 85)
s2 = Student("小红", 92)

s1.print_info()    # 小明: 85分
s2.print_info()    # 小红: 92分

二、类 = 蓝图,对象 = 实物

  • 类(class):一张设计蓝图,定义了"学生应该有什么属性和方法"
  • 对象(object):根据蓝图造出来的具体实例
python 复制代码
class Dog:
    """狗类"""

    # 类属性(所有实例共享)
    species = "Canis familiaris"

    # __init__ 是构造方法,创建对象时自动调用
    def __init__(self, name, age):
        # 实例属性(每个实例自己的数据)
        self.name = name
        self.age = age

    # 实例方法(第一个参数必须是 self)
    def bark(self):
        print(f"{self.name}:汪汪!")

    def info(self):
        return f"{self.name},{self.age}岁,{self.species}"

# 创建实例
dog1 = Dog("旺财", 3)
dog2 = Dog("大黄", 5)

dog1.bark()          # 旺财:汪汪!
print(dog1.info())   # 旺财,3岁,Canis familiaris
print(dog2.info())   # 大黄,5岁,Canis familiaris

三、class 的核心三要素

1. __init__ ------ 构造函数

python 复制代码
class Book:
    def __init__(self, title, author, pages=0):
        self.title = title
        self.author = author
        self.pages = pages
        print(f"创建了《{title}》")

# 创建对象时传入参数,__init__ 自动执行
b = Book("三体", "刘慈欣", 300)
# 输出:创建了《三体》

2. self ------ 指代"自己"

python 复制代码
class Counter:
    def __init__(self):
        self.count = 0    # self.count 是"这个实例的 count"

    def increment(self):
        self.count += 1   # 修改"自己"的 count
        print(f"当前计数:{self.count}")

c1 = Counter()
c2 = Counter()

c1.increment()    # 1
c1.increment()    # 2
c2.increment()    # 1  (c2 是另一个实例,count 独立)

self 不是关键字,写成 this 也可以(但不建议,社区规定用 self)。调用时不需要传 self,Python 会自动传

3. 实例属性 vs 类属性

python 复制代码
class Student:
    school = "海淀小学"     # 类属性(所有实例共享)

    def __init__(self, name):
        self.name = name    # 实例属性(每个实例独立)

s1 = Student("小明")
s2 = Student("小红")

print(s1.school)    # 海淀小学
print(s2.school)    # 海淀小学

# 修改类属性 → 所有人都变了
Student.school = "朝阳小学"
print(s1.school)    # 朝阳小学

# 但如果通过实例赋值 → 只给这个实例创建了同名的实例属性
s1.school = "自定义学校"
print(s1.school)    # 自定义学校(实例属性覆盖了类属性)
print(s2.school)    # 朝阳小学(还是类属性)

四、实战:银行账户类

python 复制代码
class BankAccount:
    """银行账户"""

    # 类属性
    bank_name = "中国银行"
    total_accounts = 0

    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance
        self.transactions = []     # 交易记录
        BankAccount.total_accounts += 1

    def deposit(self, amount):
        """存款"""
        if amount <= 0:
            print("存款金额必须大于0")
            return False
        self.balance += amount
        self.transactions.append(f"存入 +{amount}")
        print(f"存款成功!余额:{self.balance}")
        return True

    def withdraw(self, amount):
        """取款"""
        if amount <= 0:
            print("取款金额必须大于0")
            return False
        if amount > self.balance:
            print(f"余额不足!当前余额:{self.balance}")
            return False
        self.balance -= amount
        self.transactions.append(f"取出 -{amount}")
        print(f"取款成功!余额:{self.balance}")
        return True

    def show_info(self):
        print(f"\n户主:{self.owner}")
        print(f"银行:{self.bank_name}")
        print(f"余额:{self.balance}元")
        print(f"交易记录:")
        for t in self.transactions:
            print(f"  {t}")

# 使用
acc1 = BankAccount("小明", 1000)
acc1.deposit(500)
acc1.withdraw(200)
acc1.show_info()

acc2 = BankAccount("小红", 2000)
print(f"\n总开户数:{BankAccount.total_accounts}")   # 2

五、__str____repr__------让打印更友好

python 复制代码
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __str__(self):
        """print() 时调用,给用户看的"""
        return f"学生 {self.name},成绩 {self.score} 分"

    def __repr__(self):
        """调试时调用,给开发者看的"""
        return f"Student(name='{self.name}', score={self.score})"

s = Student("小明", 85)
print(s)              # 学生 小明,成绩 85 分
print(repr(s))        # Student(name='小明', score=85)

六、今日学习总结

学习内容 掌握情况 一句话要点
类 vs 对象 ✅ 理解 类是蓝图,对象是实物
__init__ 构造方法 ✅ 重点 创建对象时自动调用,初始化属性
self 参数 ✅ 重点 指代当前实例,调用时不用传
实例属性 vs 类属性 ✅ 理解 实例属性 self.x,类属性直接写在类里
__str__ / __repr__ ✅ 了解 控制打印输出

今日踩坑记录

  1. 忘记写 selfdef deposit(amount): 会报错 "takes 1 argument but 2 were given"。第一个参数必须是 self。
  2. 把所有属性都写成类属性class Student: name = "" 这种写法所有实例共享 name,改一个全都改。实例属性必须写在 __init__ 里用 self.xxx
  3. print(对象) 显示 <__main__.Student at 0x...> :因为没有定义 __str__ 方法,Python 只能用默认的表示。加上 __str__ 就好了。

七、明天学什么?

今天学会了创建简单的类和对象。明天继续 OOP 进阶------继承、多态、封装,这是面向对象的三大支柱。


面向对象是一种思维方式:先想"有什么东西"(对象),再想"它们能做什么"(方法)。用现实世界的方式理解代码。
第25天,打卡完成。明天见!


本系列是个人学习笔记,如有错误欢迎在评论区指正交流。

相关推荐
sunfdf2 小时前
Next.js 新手从零部署到首跑实战指南
开发语言·javascript·ecmascript
hold?fish:palm2 小时前
从源码到可执行文件:C++程序的编译过程
开发语言·c++
随性而行3603 小时前
微信API接口与AI自动化:开发者的实现思路
运维·服务器·开发语言·人工智能·微信·自动化
lingran__3 小时前
C++_STL简介
开发语言·c++
旋律翼23 小时前
Qt Bridges for C# 深度技术解析
开发语言·qt·c#
弹简特3 小时前
【Java项目-企悦抽】07-用户与认证模块-实现用户注册01
java·开发语言
L歪歪君3 小时前
Apache Doris全链路性能优化实战指南:从架构设计到生产落地
java·开发语言·算法
Csvn3 小时前
Python 开发技巧:标准库深度挖掘
后端·python
li星野3 小时前
二分查找的三重变奏:有序区间、旋转最小值与平方根——从“猜数字”到“向量检索”的思维演化
python