☰
python-mastery 练习 1.5:用 Stock 类掌握 Python 对象与类定义
2026/10/5 4:45:20 网站建设 项目流程
  • 示例工程
  • 教程

【免费下载链接】python-mastery

Advanced Python Mastery (course by @dabeaz)

项目地址:https://gitcode.com/gh_mirrors/py/python-mastery
点击查看免费下载

本篇技术指南聚焦 David Beazley 的《Advanced Python Mastery》课程第一部分——Python 复习(Python Review)中的第 5 个练习(Exercise 1.5)。它以定义一个简单的Stock股票对象为核心,完整演示了 Python 类的定义、__init__构造方法、实例属性与方法调用的全过程。读完本文,你将能够在自己的项目里写出第一个可复用的数据模型类,并能在交互式解释器中像课程要求那样熟练地创建对象、读取属性、调用方法,为后续练习中类的进阶用法(如属性校验、继承、描述符等)打下基础。

练习背景与目标

在课程的整体安排中,练习 1.1 到 练习 1.6 属于第一章节 "Python Review" 的六个练习。Exercise 1.5 处于承上启下的位置:

  • 前一个练习 Exercise 1.4 教你如何把pcost.py程序改造成portfolio_cost(filename)函数,并引入try/except异常处理;
  • 后一个练习 Exercise 1.6 则将pcost.py与stock.py作为模块导入,讲解import语句与if __name__ == '__main__'的用法;
  • Exercise 1.5 本身则专注于最简单的对象定义——回顾如何定义一个简单的对象(Review of how to define a simple object)。

本练习将创建新文件stock.py,没有任何已有文件需要修改(Files Created:stock.py)。它是全课程中第一个正式引入"类(class)"的练习,后续第 3 章(Classes and Objects)的练习(如 Exercise 3.1 及 解决方案)会在此基础上不断增加新方法(如sell()方法)与读取 CSV 数据的read_portfolio()函数。

注意:本练习的所有工作均在仓库根目录python-mastery下进行,仓库中的 Data/ 目录存放课程用到的数据文件(如portfolio.dat、portfolio.csv),Solutions/ 目录则存放每个练习的完整参考实现,例如 Solutions/1_5/stock.py。

(a) 定义一个简单的对象:创建 stock.py 并定义 Stock 类

完整的类定义代码

在python-mastery仓库根目录下新建文件stock.py,并在其中输入以下内容:

class Stock: def __init__(self, name, shares, price): self.name = name self.shares = shares self.price = price def cost(self): return self.shares * self.price

这段代码定义了名为Stock的类,包含两个成员:

成员类型作用
__init__(self, name, shares, price)构造方法(特殊方法)在创建对象时自动调用,把传入的参数保存为实例属性self.name、self.shares、self.price
cost(self)普通方法计算并返回该股票持仓的总成本,即shares * price

仓库中的参考实现 Solutions/1_5/stock.py 与上述代码完全一致,说明这就是本练习的标准答案。

逐行拆解:__init__构造方法与实例属性

  • class Stock:关键字class声明一个新的类,类名Stock通常采用驼峰命名法(CapWords);
  • def __init__(self, name, shares, price):是 Python 的构造方法。当执行Stock('GOOG', 100, 490.10)时,Python 会自动调用__init__,并自动把新创建的对象作为第一个参数self传入;
  • self.name = name等三行把外部传入的参数分别绑定到对象自身的属性上。self指代"当前这个实例",通过self.xxx = xxx创建的属性属于实例属性(instance attribute),每个实例各自独立存储一份;
  • def cost(self):定义实例方法,同样以self作为第一个参数,方法内部通过self.shares和self.price读取当前实例的属性并做乘法运算。

为什么先学这个"最简单"的对象?

从课程视角看,Stock类虽然简单,但它完整覆盖了 Python 面向对象编程的三个最基本要素:类定义、构造方法与实例属性、实例方法。你之后在 Exercise 1.6 中会通过from stock import Stock导入它,在 Exercise 3.1 及之后的练习中会为其添加sell()方法、属性校验(@property)等内容——可以说本练习的Stock是贯穿整个课程后续章节的核心模型对象。

交互式实验:创建对象并调用方法与属性

完成stock.py后,在与stock.py相同的目录下启动 Python 解释器(本练习没有__main__代码块,直接运行不会产生输出,因此建议进入交互模式实验),逐条输入以下命令:

>>> s = Stock('GOOG',100,490.10) >>> s.name 'GOOG' >>> s.shares 100 >>> s.price 490.1 >>> s.cost() 49010.0 >>> print('%10s %10d %10.2f' % (s.name, s.shares, s.price)) GOOG 100 490.10 >>> t = Stock('IBM', 50, 91.5) >>> t.cost() 4575.0 >>>

实验结果逐条解读

  1. s = Stock('GOOG',100,490.10):调用构造方法创建实例。注意490.10在内部被保存为浮点数490.1,所以后面读取s.price显示为490.1;
  2. s.name、s.shares、s.price:直接读取实例属性,无需调用任何方法;
  3. s.cost():调用实例方法,cost内部计算100 * 490.10 = 49010.0,返回浮点数;
  4. print('%10s %10d %10.2f' % (s.name, s.shares, s.price)):使用老式字符串格式化%操作符,把三个属性分别按宽度 10 的字符串、宽度 10 的整数、保留两位小数的浮点数输出,得到整齐对齐的表格行GOOG 100 490.10。这种格式化风格在后继练习(例如 Exercise 3.1 的print_portfolio表格输出,参见 Solutions/3_1/stock.py)中还会反复出现;
  5. t = Stock('IBM', 50, 91.5):创建第二个完全独立的实例,验证实例属性互不影响——t.cost()得到50 * 91.5 = 4575.0。

关键知识点:实例是相互独立的

上述实验中s与t是两个不同的对象,各自拥有一份name、shares、price属性副本。修改s.shares不会影响t.shares。这正是面向对象编程中"类是模板、实例是数据载体"的核心思想,也是后续练习中把多个Stock实例放进一个列表(portfolio)来管理投资组合的基础。

与其他练习的衔接:stock.py 在课程中的延伸

Exercise 1.5 的stock.py并非孤立存在,它在课程中会被反复复用:

  • 作为模块导入:下一个练习 Exercise 1.6 要求用from stock import Stock导入该类并创建对象:
    >>> from stock import Stock >>> s = Stock('GOOG', 100, 490.10) >>> s.name 'GOOG' >>> s.cost() 49010.0

    由此可见本练习创建的类定义方式必须保证模块可导入、类可实例化,这为第 1.6 节的 import 机制练习提供了素材;

  • 类的持续演化:到了第 3 章,Solutions/3_1/stock.py 在原有Stock类上新增了sell(self, nshares)方法(减少持仓)以及read_portfolio()/print_portfolio()两个模块级函数,后者直接从 CSV 文件(如 Data/portfolio.csv)读取数据并构造Stock实例列表——这一模式正是Stock类从"简单对象"走向"真实数据模型"的演变路径;
  • 数据文件的对应关系:本练习虽未要求读取数据文件,但课程配套的 Data/portfolio.dat 中的每一行(如AA 100 32.20)本质上都可以被建模为一个Stock('AA', 100, 32.20)实例,这也是第 3 章练习用 CSV 文件构造 portfolio 列表时的数据来源。

常见问题与调试提示

  1. 运行python3 stock.py没有任何输出?这是正常现象——本练习的stock.py只定义了类而没有调用代码,运行它不会产生任何输出。请务必进入交互式解释器(python3 -i或直接执行python3)来创建对象并实验;
  2. NameError: name 'Stock' is not defined:说明你还没有执行类的定义代码,或者你在启动解释器后没有先输入class Stock:的完整定义。请确认输入位置与stock.py文件在同一目录;
  3. 交互式实验环境提示:如 Exercise 1.4 所述,本课程后续有大量"定义函数/类后在交互解释器中实验"的场景,可以使用python3 -i stock.py让解释器运行完文件后停留在交互模式,方便继续实验;
  4. 方法调用后忘记写括号:如输入s.cost而不带(),Python 不会报错,但会返回方法对象本身(如<bound method Stock.cost of ...>),而不是计算结果——调用方法必须带上括号。

小结与下一步

Exercise 1.5 用最短的代码完成了课程中"对象与类"的第一次落地:通过class Stock定义类,通过__init__保存实例属性,通过cost()提供行为,并在交互式环境中验证了多实例的独立性。掌握本练习后,你已具备在 Python 中定义数据模型类的基本能力。

下一步建议:完成本练习后,请接着完成 Exercise 1.6,学习如何通过import stock/from stock import Stock把stock.py当作模块复用,并掌握if __name__ == '__main__'的模块化编程习惯——那是从"脚本"走向"程序"的关键一步。若在练习中卡住,可以参考仓库中的参考答案(即本练习的标准解法)或直接对照 Solutions/1_5/stock.py 的参考实现。

  • 示例工程
  • 教程

【免费下载链接】python-mastery

Advanced Python Mastery (course by @dabeaz)

项目地址:https://gitcode.com/gh_mirrors/py/python-mastery
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询