简介
在这个实验中,你将学习 Python 模块。Python 模块是包含 Python 代码的文件,可以在其他程序中导入和使用。这种模块化方法有助于代码复用,并将程序组织成逻辑组件。
你将了解什么是 Python 模块以及它们为何有用,学习如何创建自己的模块,练习以不同方式使用 import 语句,并掌握主模块的概念以及代码的执行时机。你需要具备 Python 语法和函数的基础知识,熟悉创建和运行 Python 脚本。建议在开始本练习前重启 Python 解释器会话,以确保环境干净。
在这个实验中,你将学习 Python 模块。Python 模块是包含 Python 代码的文件,可以在其他程序中导入和使用。这种模块化方法有助于代码复用,并将程序组织成逻辑组件。
你将了解什么是 Python 模块以及它们为何有用,学习如何创建自己的模块,练习以不同方式使用 import 语句,并掌握主模块的概念以及代码的执行时机。你需要具备 Python 语法和函数的基础知识,熟悉创建和运行 Python 脚本。建议在开始本练习前重启 Python 解释器会话,以确保环境干净。
在 Python 中,模块就像是一个容器,用于存放 Python 定义和语句。它本质上是一个文件,文件名就是模块名,后面加上 .py 扩展名。可以把模块想象成工具箱,它们能帮助你以逻辑的方式组织 Python 代码,使其更易于复用和维护。就像你会把不同的工具放在不同的盒子里以便更好地整理一样,你可以将相关的 Python 代码分组到不同的模块中。
让我们来看看为这个实验准备的文件:
stock.py 文件,看看里面的内容。为此,我们将使用以下命令。cd 命令用于将目录更改为 project 文件夹,我们的文件就位于该文件夹中,cat 命令用于显示文件的内容。cd ~/project
cat stock.py
这个 stock.py 文件定义了一个 Stock 类。类就像是创建对象的蓝图。在这种情况下,Stock 类代表一支股票。它有股票名称、股数和价格等属性(类似于特征),还有一个用于计算股票成本的方法(类似于与类关联的函数)。
pcost.py 文件。我们将再次使用 cat 命令来查看其内容。cat pcost.py
这个文件定义了一个名为 portfolio_cost() 的函数。函数是执行特定任务的代码块。portfolio_cost() 函数读取一个投资组合文件,并计算该投资组合中所有股票的总成本。
cat 命令查看 portfolio.dat 文件的内容。cat portfolio.dat
这个文件以简单的格式包含股票数据。每行包含股票的代码、股数和每股价格。
import 语句Python 的 import 语句是一个强大的工具,它允许你在当前程序中使用其他模块的代码。这就像从其他工具箱中借用工具一样。让我们练习以不同的方式导入代码:
python3
pcost 模块,看看会发生什么。当我们使用 import 语句时,Python 会查找 pcost.py 文件,并使其中的代码可供我们使用。import pcost
你应该会看到输出 44671.15。这是根据 portfolio.dat 文件计算出的投资组合成本。当 pcost 模块被导入时,pcost.py 文件底部的代码会自动运行。
portfolio_cost() 函数。我们将使用 pcost.portfolio_cost() 语法从 pcost 模块调用该函数。pcost.portfolio_cost('portfolio2.dat')
输出应该是 19908.75,这代表第二个投资组合文件中股票的总成本。
stock 模块导入特定的类。我们可以使用 from...import 语句只导入 Stock 类,而不是导入整个模块。from stock import Stock
Stock 类后,我们可以创建一个 Stock 对象。对象是类的实例。我们将创建一个名为 GOOG、有 100 股、价格为 490.10 的 Stock 对象。然后,我们将打印股票名称并使用 cost() 方法计算其成本。s = Stock('GOOG', 100, 490.10)
print(s.name)
print(s.cost())
输出应该是:
GOOG
49010.0
exit() 函数退出。exit()
这个实验展示了两种不同的导入 Python 代码的方式:
import module_name - 这会导入整个模块,使该模块中的所有函数、类和变量都可供使用。from module_name import specific_item - 这只从模块中导入特定的项(如类或函数),如果你只需要模块的部分功能,这种方式很有用。在 Python 中,当你直接运行一个脚本时,它会作为“主”模块。Python 有一个特殊的变量 __name__。当一个文件被直接执行时,Python 会将 __name__ 的值设置为 "__main__"。这与该文件作为模块被导入时的情况不同。
这个特性非常有用,因为它允许你编写根据文件是直接运行还是被导入而表现不同的代码。例如,你可能希望某些代码仅在将文件作为脚本执行时运行,而在它被另一个脚本导入时不运行。
pcost.py 以使用主模块模式让我们修改 pcost.py 程序以利用这种模式。
pcost.py 文件。你可以使用以下命令导航到项目目录,并在文件不存在时创建它:cd ~/project
touch pcost.py
cd 命令将当前目录更改为你主目录下的 project 目录。touch 命令会在 pcost.py 文件不存在时创建一个新的该文件。
pcost.py 文件修改为如下内容:## pcost.py
def portfolio_cost(filename):
total_cost = 0.0
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
nshares = int(fields[1])
price = float(fields[2])
total_cost += nshares * price
except (ValueError, IndexError):
print(f"Couldn't parse: {line}")
return total_cost
## 此代码仅在文件作为脚本执行时运行
if __name__ == "__main__":
total = portfolio_cost('portfolio.dat')
print(total)
这里的主要更改是,我们将末尾的代码包装在 if __name__ == "__main__": 条件语句中。这意味着该代码块内的代码仅在文件作为脚本直接执行时运行,而在它作为模块被导入时不运行。
现在,让我们以两种不同的方式测试我们修改后的模块,看看它的表现如何。
python3 pcost.py
你应该会看到输出 44671.15,和之前一样。这是因为当你直接运行脚本时,__name__ 变量被设置为 "__main__",所以 if __name__ == "__main__": 代码块内的代码会被执行。
python3
import pcost
这次,你不会看到任何输出。当你导入模块时,__name__ 变量被设置为 "pcost"(模块名),而不是 "__main__"。因此,if __name__ == "__main__": 代码块内的代码不会运行。
portfolio_cost 函数仍然可以正常工作,你可以像这样调用它:pcost.portfolio_cost('portfolio.dat')
该函数应该返回 44671.15,这意味着它工作正常。
exit()
这种模式在创建既可以作为可导入模块又可以作为独立脚本使用的 Python 文件时非常有用。if __name__ == "__main__": 代码块内的代码仅在文件被直接执行时运行,而在它作为模块被导入时不运行。
既然你已经了解了如何使用现有的模块,那么现在是时候从头开始创建一个新模块了。在 Python 中,模块是一个包含 Python 定义和语句的文件。它允许你将代码组织成可复用且易于管理的部分。通过创建自己的模块,你可以将相关的函数和变量组合在一起,使你的代码更具模块化,也更易于维护。
让我们创建一个简单的模块来生成股票报告。这个模块将包含读取投资组合文件并打印投资组合中股票格式化报告的函数。
report.py 的新文件。为此,我们将使用命令行。导航到你主目录下的 project 目录,并使用 touch 命令创建该文件。cd ~/project
touch report.py
report.py 文件,并添加以下代码。这段代码定义了两个函数和一个主程序块。## report.py
def read_portfolio(filename):
"""
Read a stock portfolio file into a list of dictionaries with
keys: name, shares, price
"""
portfolio = []
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
stock = {
'name': fields[0],
'shares': int(fields[1]),
'price': float(fields[2])
}
portfolio.append(stock)
except (ValueError, IndexError):
print(f"Couldn't parse: {line}")
return portfolio
def print_report(portfolio):
"""
Print a report showing the stock name, shares, price, and total value
"""
print("Name Shares Price Value")
print("-" * 40)
total_value = 0.0
for stock in portfolio:
value = stock['shares'] * stock['price']
total_value += value
print(f"{stock['name']:6s} {stock['shares']:9d} {stock['price']:9.2f} {value:9.2f}")
print("-" * 40)
print(f"Total Value: {total_value:16.2f}")
if __name__ == "__main__":
portfolio = read_portfolio('portfolio.dat')
print_report(portfolio)
read_portfolio 函数读取包含股票信息的文件,并返回一个字典列表,其中每个字典代表一支股票,包含 name、shares 和 price 键。print_report 函数接受一个投资组合(股票字典列表),并打印一个格式化的报告,显示股票名称、股数、价格和总价值。末尾的主程序块在文件直接执行时运行,它读取投资组合文件并打印报告。
让我们测试我们的新模块,确保它按预期工作。
report.py 文件中的主程序块。python3 report.py
你应该会看到一个格式化的报告,显示投资组合中的股票及其价值。该报告包括股票名称、股数、价格和总价值,以及整个投资组合的总价值。
Name Shares Price Value
----------------------------------------
AA 100 32.20 3220.00
IBM 50 91.10 4555.00
CAT 150 83.44 12516.00
MSFT 200 51.23 10246.00
GE 95 40.37 3835.15
MSFT 50 65.10 3255.00
IBM 100 70.44 7044.00
----------------------------------------
Total Value: 44671.15
python3 命令启动 Python 解释器。python3
解释器启动后,我们可以导入 report 模块并使用其函数。
import report
portfolio = report.read_portfolio('portfolio.dat')
len(portfolio) ## Should return 7, the number of stocks
portfolio[0] ## First stock in the portfolio
import report 语句使 report.py 文件中定义的函数和变量在当前 Python 会话中可用。然后,我们使用 read_portfolio 函数读取投资组合文件,并将结果存储在 portfolio 变量中。len(portfolio) 语句返回投资组合中的股票数量,portfolio[0] 返回投资组合中的第一支股票。
你应该会看到以下输出:
7
{'name': 'AA', 'shares': 100, 'price': 32.2}
total = 0.0
for stock in portfolio:
total += stock['shares'] * stock['price']
print(total)
输出应该是 44671.15,这与 print_report 函数打印的总价值相同。
print_report 函数为这些股票打印报告。ibm_stocks = [stock for stock in portfolio if stock['name'] == 'IBM']
report.print_report(ibm_stocks)
这应该会打印一个只显示 IBM 股票及其价值的报告。
Name Shares Price Value
----------------------------------------
IBM 50 91.10 4555.00
IBM 100 70.44 7044.00
----------------------------------------
Total Value: 11599.00
exit() 命令退出 Python 解释器。exit()
你现在已经成功创建并使用了自己的 Python 模块,它结合了函数和一个仅在文件直接执行时运行的主程序块。这种模块化的编程方法允许你复用代码,使你的项目更有条理且易于维护。
在本次实验中,你学习了 Python 模块的基本概念,以及如何使用它们来组织代码。模块是包含可复用代码的 Python 文件,而 import 语句使你能够在程序中使用其他模块的代码。if __name__ == "__main__" 模式允许文件既可以作为可导入的模块,也可以作为独立的脚本。
这些概念对于编写可维护的 Python 代码至关重要,尤其是在开发大型应用程序时。在你继续学习 Python 的过程中,请记住,模块有助于将相关代码分组,导入特定项可以保持命名空间的整洁,而主模块模式是一种最佳实践。应用这些技术将使你的代码更有条理、更易于维护且可复用性更强。