Python类与对象实战:从基础语法到模块化编程

1. 为什么说“万物皆对象”?从生活到代码的类与对象初体验

刚学Python那会儿,听到“类”和“对象”这两个词,总觉得特别抽象,像是教科书里硬邦邦的概念。直到有一次,我想写个小程序来管理我收藏的几百本书,情况才彻底改变。我发现,如果不用“类”,我的代码会变得一团糟:每本书的信息都用独立的变量存,找起来麻烦,想统一做个操作(比如批量改个价格)更是得写一堆重复的代码。那一刻我突然明白了,类(Class)其实就是我们给现实世界中的“一类事物”画的蓝图,而对象(Object)就是根据这张蓝图造出来的、活生生的具体东西

就拿“书”来举例。世界上有无数本书,但每本书都有一些共同的“特征”和“行为”。特征就是属性,比如书名、作者、出版日期、版本;行为就是方法,比如可以被出售、可以被借阅、可以显示简介。我们不需要为每一本具体的《Python编程从入门到实践》都重新发明一套描述体系,只需要定义一次“书”这个类,然后“生产”出一个个具体的书对象就行了。这个过程,就叫实例化

下面这个最简单的类定义,就是那张“蓝图”:

class Book:
    """一个简单的书籍类"""
    pass

class 是定义类的关键字,Book 是我们给这个类起的名字,按照惯例,类名首字母大写。里面的 pass 是个占位符,意思是“这里暂时啥也不干”。虽然这个类现在空空如也,但我们已经可以拿它来“造”对象了:

# 根据Book类,创建两个具体的书对象
my_book = Book()
your_book = Book()

print(type(my_book))  # 输出:<class '__main__.Book'>
print(my_book is your_book)  # 输出:False

看,my_bookyour_book 都是 Book 类的实例,也就是对象。type() 函数告诉我们它的类型是 Book。最关键的是最后一行,它证明了两者虽然“长相”一样(都是Book类造的),但却是内存中两个完全独立、互不干扰的个体,就像用同一个模具压出来的两块饼干。

但光有个空壳子没用,我们的书还得有名字和作者。这就需要用到类里面一个非常特殊的方法:__init__()。你可以把它理解为对象的“出生证明”填写处,或者叫构造方法。当使用 Book() 创建对象时,Python会自动调用这个方法。我们可以在里面定义对象刚诞生时就必须要有的属性。

2. 让对象“活”起来:构造方法与实例属性

让我们把刚才那个“空壳”Book类升级一下,赋予它真正的属性。__init__ 方法的第一参数永远是 self,你可以把它看作对象自己的“代号”或者“身份证”。在方法内部,我们通过 self.属性名 = 参数 的方式,把外部传入的数据“绑定”到这个对象身上,这些绑定的数据就叫实例属性

class Book:
    """一个带有初始化方法的书籍类"""
    def __init__(self, name, author, data, version=1):
        self.name = name      # 书名
        self.author = author  # 作者
        self.data = data      # 出版日期
        self.version = version # 版本,默认为1
        self.is_sold = False  # 销售状态,每个新书对象默认未售出

这次,创建对象时就必须提供必要信息了:

# 创建一本具体的书对象
book1 = Book("Python核心编程", "Wesley Chun", "2022-10-01", 3)
book2 = Book("流畅的Python", "Luciano Ramalho", "2021-05-01")

print(f"书名:{book1.name}, 作者:{book1.author}, 版本:v{book1.version}")
print(f"书名:{book2.name}, 版本:v{book2.version}")  # 使用了默认版本号1

注意到区别了吗?book1book2 拥有各自独立的 nameauthor 等属性。修改 book1.name 绝不会影响 book2.name。这里的 version=1 是默认参数,意味着如果创建时不指定版本,就会自动设为1,这在实际编程中非常常用,能给函数和方法调用带来很大的灵活性。

属性有了,对象还应该能“做事”。比如,书可以卖。这就是我们要给类添加的实例方法。实例方法的第一个参数也必须是 self,这样方法内部才能操作这个对象自己的属性。

class Book:
    def __init__(self, name, author, data, version=1):
        self.name = name
        self.author = author
        self.data = data
        self.version = version
        self.is_sold = False
        self.price = 0  # 新增一个价格属性,初始为0

    # 定义一个卖书的方法
    def sell(self, price):
        """设置价格并标记为已售出"""
        if price <= 0:
            print("价格必须为正数!")
            return
        self.price = price
        self.is_sold = True
        print(f"《{self.name}》已售出,售价:{self.price}元")

    # 定义一个介绍自己的方法
    def introduce(self):
        print(f"您好,这是《{self.name}》,作者是{self.author},当前是第{self.version}版。")

现在,我们的书对象能“行动”了:

my_novel = Book("三体", "刘慈欣", "2008-01-01")
my_novel.introduce()  # 输出:您好,这是《三体》,作者是刘慈欣,当前是第1版。
my_novel.sell(68)     # 输出:《三体》已售出,售价:68元
print(f"是否已售:{my_novel.is_sold}")  # 输出:是否已售:True

方法 sell 不仅接收一个外部参数 price,更重要的是,它通过 self 修改了对象自身的状态(self.priceself.is_sold)。这就是面向对象编程的核心魅力:数据(属性)和操作数据的方法被捆绑在一起,封装在对象内部。你不用去记忆和操作一堆散乱的变量,而是直接对“书”这个整体对象下命令,代码的逻辑立刻变得清晰自然。

3. 不仅仅是实例:深入类方法与静态方法

到目前为止,我们接触的方法都需要先创建一个对象(实例),然后通过这个对象来调用,比如 my_novel.sell(68)。这类方法我们称之为实例方法,它们主要用来处理单个对象的数据。但有时候,我们需要一些功能,它和类相关,但又不需要(或不适合)操作某个具体的对象。Python 为我们提供了 类方法(Class Method)静态方法(Static Method)

先说说类方法。它的标志是使用装饰器 @classmethod,并且第一个参数不是 self,而是 cls,代表类本身。类方法最常见的用途是作为“替代构造器”,或者操作那些属于整个类(而不是单个对象)的属性(类属性)。

假设我们的书店对所有书都有一个统一的折扣率,这个折扣率不属于任何一本具体的书,而是书店的全局策略。我们可以把它定义为类属性,然后通过类方法来修改或应用它。

class BookStore:
    # 类属性,所有对象共享
    store_discount = 0.9  # 默认9折
    total_books_sold = 0   # 书店售出的书的总数

    def __init__(self, name, price):
        self.name = name
        self.base_price = price  # 基础价格

    def final_price(self):
        """计算折后价:实例方法,可以访问实例属性和类属性"""
        return self.base_price * BookStore.store_discount

    @classmethod
    def change_discount(cls, new_discount):
        """类方法:修改整个书店的折扣"""
        if 0 < new_discount <= 1:
            cls.store_discount = new_discount
            print(f"全店折扣已更新为:{new_discount}")
        else:
            print("折扣必须在0到1之间")

    @classmethod
    def book_sold(cls):
        """类方法:每卖出一本书,总数加1"""
        cls.total_books_sold += 1

# 使用类方法,无需创建对象
BookStore.change_discount(0.8)  # 直接通过类名调用

# 创建对象
book_a = BookStore("Python入门", 100)
book_b = BookStore("算法图解", 80)

# 卖书
book_a.book_sold()  # 通过对象调用类方法,cls会自动传入BookStore类
book_b.book_sold()
print(f"书店售出书籍总数:{BookStore.total_books_sold}")  # 输出:2

print(f"《{book_a.name}》折后价:{book_a.final_price()}")  # 输出:80.0 (100*0.8)

再看静态方法。它使用装饰器 @staticmethod,既不需要 self 参数,也不需要 cls 参数。它就像一个被塞进类里的普通函数,仅仅是因为它在逻辑上与这个类相关,放在里面便于组织代码。静态方法不能访问或修改任何实例属性或类属性。

class BookStore:
    store_discount = 0.9

    @staticmethod
    def calculate_tax(price, tax_rate=0.06):
        """静态方法:计算税费。与具体哪本书无关,只是一个计算工具。"""
        return price * tax_rate

    @staticmethod
    def is_valid_isbn(isbn_str):
        """静态方法:简单校验ISBN格式(示例,非完整校验)"""
        return len(isbn_str) == 13 and isbn_str.isdigit()

# 使用静态方法,同样无需对象
tax = BookStore.calculate_tax(100)
print(f"100元商品的税费是:{tax}元")  # 输出:6.0

is_valid = BookStore.is_valid_isbn("9787111128069")
print(f"ISBN是否有效:{is_valid}")  # 输出:True

提示:怎么快速区分这三种方法?问自己一个问题:这个方法需要知道是“谁”在调用它吗?如果需要操作或知道具体某本书的信息(如书名、价格),用实例方法。如果只需要知道是哪个书店(哪个类)的政策,用类方法。如果只是一个和书相关的通用工具函数,跟具体哪本书、哪个店都无关,用静态方法

4. 代码的积木:模块化编程与类的导入

当你写的类越来越多,功能越来越复杂,把所有代码都堆在一个文件里会变得难以维护。想象一下,你把建造房子的所有图纸(类)、工具(函数)、材料(变量)都写在一张巨大的纸上,找起来得多崩溃。Python的模块化就是来解决这个问题的:把相关的代码分门别类地放到不同的文件(模块)里,然后用“导入”的方式像搭积木一样组合起来。

一个 .py 文件就是一个模块。我们可以把 Book 类和 BookStore 类分别保存到不同的文件中。假设我们有一个 book.py 文件,内容如下:

# book.py 文件
class Book:
    def __init__(self, name, author):
        self.name = name
        self.author = author

    def introduce(self):
        return f"Book: {self.name} by {self.author}"

还有一个 bookstore.py 文件:

# bookstore.py 文件
class BookStore:
    store_name = "Python书店"

    @staticmethod
    def welcome():
        print(f"欢迎来到{BookStore.store_name}!")

现在,在另一个主程序文件 main.py 中,我们就可以像导入标准库一样导入我们自己写的模块和类了。导入方式非常灵活,常见的有以下几种:

方式一:导入整个模块

# main.py
import book
import bookstore

# 使用时需要带上模块名
my_book = book.Book("深入浅出Python", "Paul Barry")
print(my_book.introduce())

bookstore.BookStore.welcome()

方式二:从模块中导入特定的类或函数

# main.py
from book import Book
from bookstore import BookStore

# 现在可以直接使用类名,无需模块前缀
my_book = Book("Effective Python", "Brett Slatkin")
print(my_book.introduce())

BookStore.welcome()

方式三:导入模块并起别名(常用于模块名很长时)

# main.py
import bookstore as bs
from book import Book as Bk

my_book = Bk("Python Cookbook", "David Beazley")
bs.BookStore.welcome()

方式四:导入模块中的所有内容(不推荐,容易引起命名冲突)

# main.py
from book import *
from bookstore import *

# 可以直接使用,但如果有同名类或函数,后者会覆盖前者,很难调试
my_book = Book("Fluent Python", "Luciano Ramalho")

模块化带来的好处是巨大的。首先是代码复用,你写好一个通用的工具类,可以在无数个项目里 import 进来直接用,不用复制粘贴。其次是命名空间管理,不同模块里的同名函数和类不会打架。最后是结构清晰,大型项目可以按功能划分成多个包(Package,即包含 __init__.py 的文件夹)和模块,像 models/ 放数据类,utils/ 放工具函数,services/ 放业务逻辑,一目了然。

在实际项目中,你可能会遇到循环导入的问题(A模块导入了B,B又导入了A),这通常意味着你的代码结构需要优化。一个基本原则是:让依赖关系单向流动。高层模块可以依赖底层模块,但底层模块尽量不要依赖高层模块。如果确实需要共享某些东西,可以考虑把它们抽离到一个独立的、更基础的第三方模块中。

5. 实战:构建一个简易的图书馆管理系统

理论说了这么多,我们来个实战,把前面学的类、对象、方法、模块全部用上,构建一个超级简易但五脏俱全的“命令行图书馆管理系统”。我们会创建三个文件,模拟一个简单的模块化项目结构。

第一步:创建数据模型(models.py 这个文件专门存放我们的核心类,代表系统中的“实体”。

# models.py
class Book:
    """图书类"""
    def __init__(self, isbn, title, author, is_borrowed=False):
        self.isbn = isbn          # 国际标准书号,唯一标识
        self.title = title        # 书名
        self.author = author      # 作者
        self.is_borrowed = is_borrowed # 是否被借出

    def get_info(self):
        status = "已借出" if self.is_borrowed else "在馆"
        return f"ISBN: {self.isbn} | 《{self.title}》 - {self.author} | 状态: {status}"

    def borrow(self):
        if self.is_borrowed:
            return f"《{self.title}》已被借出,无法再借。"
        else:
            self.is_borrowed = True
            return f"成功借出《{self.title}》。"

    def return_book(self):
        if not self.is_borrowed:
            return f"《{self.title}》本就在馆,无需归还。"
        else:
            self.is_borrowed = False
            return f"感谢归还《{self.title}》。"


class Member:
    """会员类"""
    def __init__(self, member_id, name):
        self.member_id = member_id
        self.name = name
        self.borrowed_books = []  # 借阅的图书列表

    def borrow_book(self, book):
        if len(self.borrowed_books) >= 5:  # 假设每人最多借5本
            return f"{self.name},您借书已达上限。"
        if book.is_borrowed:
            return f"抱歉,《{book.title}》已被他人借走。"
        result = book.borrow()
        if "成功" in result:
            self.borrowed_books.append(book)
        return result

    def return_book(self, book):
        if book in self.borrowed_books:
            result = book.return_book()
            if "感谢归还" in result:
                self.borrowed_books.remove(book)
            return result
        else:
            return f"记录显示您并未借阅《{book.title}》。"

    def show_my_books(self):
        if not self.borrowed_books:
            return f"{self.name},您当前没有借阅任何书籍。"
        book_list = "\n".join([f"  - {b.title}" for b in self.borrowed_books])
        return f"{self.name}借阅的书籍:\n{book_list}"

第二步:创建图书馆管理类(library.py 这个文件作为“服务层”,管理所有的书和会员,提供核心业务逻辑。

# library.py
from models import Book, Member

class Library:
    """图书馆核心管理类"""
    def __init__(self, name):
        self.name = name
        self.books = {}      # 用字典存储,key是ISBN,value是Book对象
        self.members = {}    # key是会员ID,value是Member对象

    def add_book(self, isbn, title, author):
        if isbn in self.books:
            return f"ISBN为{isbn}的图书已存在。"
        self.books[isbn] = Book(isbn, title, author)
        return f"成功入库《{title}》。"

    def register_member(self, member_id, name):
        if member_id in self.members:
            return f"会员ID {member_id} 已被注册。"
        self.members[member_id] = Member(member_id, name)
        return f"会员 {name} 注册成功。"

    def find_book(self, keyword):
        """根据ISBN或书名关键词查找图书"""
        results = []
        for book in self.books.values():
            if keyword == book.isbn or keyword.lower() in book.title.lower():
                results.append(book)
        return results

    def show_all_books(self):
        if not self.books:
            return "图书馆暂无藏书。"
        info_list = [book.get_info() for book in self.books.values()]
        return "\n".join(info_list)

第三步:创建主程序入口(main.py 这个文件是程序的启动点,负责与用户交互,调用前面模块的功能。

# main.py
from library import Library

def main():
    # 初始化图书馆
    my_lib = Library("Python数字图书馆")

    # 预先添加一些图书和会员
    my_lib.add_book("978-7-111-12806-9", "Python编程从入门到实践", "Eric Matthes")
    my_lib.add_book("978-7-115-44559-3", "流畅的Python", "Luciano Ramalho")
    my_lib.register_member("M001", "张三")
    my_lib.register_member("M002", "李四")

    while True:
        print("\n=== Python数字图书馆管理系统 ===")
        print("1. 显示所有图书")
        print("2. 查找图书")
        print("3. 借阅图书")
        print("4. 退出")
        choice = input("请选择操作 (1-4): ")

        if choice == '1':
            print("\n--- 馆藏列表 ---")
            print(my_lib.show_all_books())

        elif choice == '2':
            keyword = input("请输入ISBN或书名关键词: ")
            books = my_lib.find_book(keyword)
            if books:
                for b in books:
                    print(b.get_info())
            else:
                print("未找到相关图书。")

        elif choice == '3':
            # 这里为了简化,省略了会员登录和选择图书的详细交互
            # 实际可以扩展:输入会员ID,查找图书ISBN,调用member.borrow_book(book)
            print("借阅功能示例:")
            member = my_lib.members.get("M001")
            if member:
                # 假设借阅第一本书
                target_isbn = "978-7-111-12806-9"
                target_book = my_lib.books.get(target_isbn)
                if target_book:
                    print(member.borrow_book(target_book))
                else:
                    print("图书不存在。")
            else:
                print("会员不存在。")

        elif choice == '4':
            print("感谢使用,再见!")
            break
        else:
            print("输入无效,请重新选择。")

if __name__ == "__main__":
    main()

运行 main.py,你就能看到一个在命令行中交互的简易图书馆系统了。这个项目虽然小,但完整地体现了面向对象编程的思想:BookMember 是数据模型,封装了各自的状态和行为;Library 是管理类,协调多个对象之间的交互;main.py 是用户界面和程序入口。通过分文件(模块)组织,代码结构清晰,职责分明。如果你想增加新功能,比如图书分类、借阅期限、逾期罚款,只需要在相应的类里添加属性和方法,或者创建新的模块,而不会让原有代码变得混乱。这就是模块化、面向对象编程带来的可维护性和可扩展性。

摘 要 随着互联网影视产业的迅速发展,电影资源呈指数级增长,型也愈加多样化,但是用户面对如此庞大的影片库时,会遇到信息过载、筛选效率低下、观影决策成本高这些难题,而传统的电影平台大多只是对基本的分和热度进行展示,并没有提供个性化的推荐服务,社交互动以及一体化管理的能力也比较薄弱。 该系统使用的是Spring Boot+Vue前后端分离的方式进行开发,设计并开发了一个电影推荐和评论系统。开发系统中存在三个问题,即无法准确地判断出用户的喜好、电影推荐功能上线之初没有用户数据,因此推荐效果不佳、大量用户同时评论打分时系统容易出现不稳定的情况。为了克服上述问题,本文查阅相关资料,不断迭代开发原型,并进行实际测试,完成整个系统的全部过程,即系统需求分析、架构设计、功能开发、系统测试。系统分为普通用户和管理员两种身份,具有注册登录、电影浏览、电影推荐、评分评论、影片收藏、个人中心、后台管理等功能,采用结合用户喜好和电影热度的简单推荐方式,提供热门电影推荐和个性化推荐,很好地解决了推荐功能初始没有数据、数据较少的问题。项目用接口来完成前后端的数据交互,使用MySQL数据库存储用户、电影、评论、收藏等各种数据,并且加入权限验证、密码加密等安全措施,保证系统安全稳定并且便于后期扩展。除此之外,系统还增加了电影资讯查看、首页轮播图设置、编辑资讯等功能,使整个电影平台的服务更加全面,使用更加高效。经过全面的功能测试、接口测试和性能测试,系统各个模块运行稳定,推荐接口响应时间小于300ms,主要的互动操作成功率大于98%,可以大大降低用户的选片成本,提高观影决策的速度和社区互动的效果。 本文给出一套轻量级、易部署、可复用的电影推荐Web应用工程实现方案,相比于传统的单一列表展示型平台,个性化服务、社交互动体验和后台管理效率都有明显的提高,可以给影视文化数字化传播、推荐算法轻量化工程实践
源码直接下载地址: https://pan.quark.cn/s/a4b39357ea24 在 Excel 中进行阳历阴历的相互转换,对于处理集体信息(例如通讯录)统计工作具有显著的实用性。本文将具体阐述如何借助 VBA 编辑器在 Excel 环境下完成阳历阴历的互换转换。首先,需要打开相应的 Excel 文件,通过按 Alt+F11 激活 VBA 编辑器,随后选择插入菜单下的模块选项,将提供的代码片段复制到新模块中,并保存更改后关闭编辑器。完成上述步骤后,即可在指定单元格中调用以下四个函数以达成转换目标。 1. 阴阳历转换功能: 函数 `Lunar(SolarDate[, Part = 0 | 1 | 2 | 3])` 负责将阳历日期转换为对应的阴历日期。参数 `Part` 决定转换内容的详略程度,其值可为 0、1、2 或 3,分别对应完整日期、阴历年、阴历月及阴历日的转换。 函数 `Solar(LunarDate[, LunarMonth = 0 | 1])` 适用于将阴历日期转换为阳历日期。参数 `LunarMonth` 用于指定月份的归属,可为 0 或 1,分别代表转换至阳历月份或保留阴历月份。 2. 生日日期转换功能: 函数 `lunarbirth("1975-5-6")` 能够计算出阴历生日所对应的阳历日期。相对地,函数 `solarbirth("1975-5-6")` 用于推算阳历生日对应的阴历日期。 3. 日期信息计算功能: 函数 `LunarData(q_year)` 提供阴历日期的详细数据,涵盖阴历年、阴历月、阴历日等信息。函数 `ConvDataA` 存储了阴历阳历的日期数据,包括阴历年、阴历月、阴历日、阳历月、阳历日等字段。 4. 应用...
下载代码方式:https://pan.quark.cn/s/a4b39357ea24 在信息技术行业中,特别是在人工智能(AI)的子领域——计算机视觉方面,动作分析是一个至关重要的组成部分。这一议题Python-PyTorch动作分析模型库”有着紧密的联系,它涵盖了运用Python编程语言和PyTorch框架来构建和应用深度学习模型,旨在解析和判定视频中的行为。接下来,我们将详细研究这一领域的重要概念。 **PyTorch** 是由Facebook开发的一个开源且功能强大的深度学习平台,它具备动态计算图特性,从而让模型构建和调试过程更加便捷。PyTorch的关键在于Tensor,该是数值运算的基础,同时支持自动计算梯度,为神经网络的训练提供了便利。 **动作分析** 是计算机视觉中的一个核心任务,其目的是识别视频中的特定行为,例如奔跑、跳跃、招手等。这项任务通常包括从视频材料中提取图像帧,然后对单个帧或帧序列进行特征提取,最终借助已训练的模型进行分。 在描述中提及的“流行动作分析模型”,或许涵盖了当前研究领域的主流模型,例如**双流卷积网络**,这种模型融合了空间和时间信息,通过分别处理RGB图像和光流图像来提高行为分析的精确度。还可能包括**时间分割网络(TSN)**,它通过跨长时间范围的样本选择来把握行为的整体特征。另外,更前沿的模型如**时间迁移模块(TSM)** 和 **非局部神经网络** 也可能被纳入其中,这些模型通过创新的网络构造来更有效地捕捉时间序列中的动态变化。 **某数据集** 可能是指像UCF-101或Kinetics这样的标准动作分析数据集,它们包含了大量标注好的视频片段,用于模型的训练和性能评估。这些数据集在动作分析研究中被...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值