当前位置:首页>python>Python 学习第 4 天:变量作用域、模块和包,代码开始有结构了

Python 学习第 4 天:变量作用域、模块和包,代码开始有结构了

  • 2026-08-28 10:48:35
Python 学习第 4 天:变量作用域、模块和包,代码开始有结构了

大家好,我是大华!

Python 学习进入第 4 天,开始学习变量的作用域,以及代码的模块化组织方式。

比如:变量该放哪?怎么模块化?还有内置函数等。

今天的文章内容可能比前几天的要多一些,于是用 AI 生成了部分配图,缓解一下阅读的疲劳。

废话不多说,直接开始了。

一、变量作用域

1.1 什么是作用域?

作用域是变量在程序中可被访问的范围,决定了变量的"可见性"和"生命周期"。

1.2 四种作用域级别(LEGB规则)

LEGB 规则分布对应下面这4个:

  • • L - Local(局部作用域):函数内部定义的变量,只有在该函数内部可见
  • • E - Enclosing(闭包作用域):嵌套函数的外层函数变量
  • • G - Global(全局作用域):模块级别定义的变量
  • • B - Built-in(内置作用域):Python内置的函数和变量

代码示例:

# 全局变量global_var = "我是全局变量"def outer_function():    # 闭包变量(外部函数变量)    outer_var = "我是外部函数变量"    def inner_function():        # 局部变量        local_var = "我是局部变量"        # 内置作用域(如print, len等)        print(local_var)          # 局部变量        print(outer_var)          # 闭包变量        print(global_var)         # 全局变量        print(len("test"))        # 内置函数    inner_function()    # print(local_var)  # 错误!无法访问内部函数的局部变量outer_function()print(global_var)  # 正确,可以访问全局变量

输出结果:

我是局部变量我是外部函数变量我是全局变量4我是全局变量

特别说明:print(len("test"))  输出的4,是内置的函数 len() 读取 test 这个字符串的长度。

1.3 global 和 nonlocal 关键字

global 关键字

声明使用全局变量。

counter = 0def increment():    global counter  # 使用全局变量    counter += 1    print(f"计数器: {counter}")increment()  # 输出: 计数器: 1increment()  # 输出: 计数器: 2

在需要使用全局变量的情况下,必须加上 global 关键字,不加会报错,如下:

counter = 0  # 全局变量def increment():    # 如果不用 global,Python会认为counter是新的局部变量    counter = counter + 1  # 这里会报错!increment() 

这个代码会报错:UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value

原因:Python 看到一个函数内部对变量赋值时,会认为这个变量是局部变量。

在 counter = counter + 1 中,右边的 counter 还没定义(局部变量),所以报错。


nonlocal 关键字

声明使用外部函数的变量

def outer():    message = "原始消息"    def inner():        nonlocal message  # 使用外部函数的变量        message = "修改后的消息"        print(f"内部函数: {message}")    inner()    print(f"外部函数: {message}")outer()

输出结果:

内部函数: 修改后的消息外部函数: 修改后的消息

如果没有 nonlocal message 这个关键字,那么输出的结果如下:

内部函数: 修改后的消息外部函数: 原始消息

原因是:outer() 里的 message 没被修改,inner() 创建了自己的局部变量。

二、模块(Module)

2.1 什么是模块?

模块是一个包含 Python 代码的.py文件,可以包含函数、类、变量等。

2.2 创建和使用模块

创建 calculator.py 文件,这是一个模块文件,然后在另一个文件导入它。

def add(a, b):    # 返回两个数的和    return a + bdef subtract(a, b):    # 返回两个数的差    return a - bdef multiply(a, b):    # 返回两个数的乘积    return a * bdef divide(a, b):    # 返回两个数的商    if b == 0:        return "错误:除数不能为零"    return a / b# 模块级别的变量PI = 3.14159VERSION = "1.0.0"

创建 main.py,在该文件导入使用 calculator.py。

这里的导入也分几种导入方式,如下:

方式1:导入整个模块

import calculator# 调用calculator模块的add函数result = calculator.add(10, 5)print(f"10 + 5 = {result}")print(f"PI值: {calculator.PI}")
方式2:导入特定功能
from calculator import add, subtract, PIresult = add(20, 10)print(f"20 + 10 = {result}")print(f"PI值: {PI}")

方式3:使用别名

import calculator as calcfrom calculator import multiply as mulresult = calc.divide(20, 4)print(f"20 ÷ 4 = {result}")result = mul(5, 6)print(f"5 × 6 = {result}")

2.3 Python 标准库常用模块

1.日期时间

使用 datetime 模块处理日期时间

import datetime# 获取当前日期和时间now = datetime.datetime.now()print(f"当前时间: {now}")print(f"日期: {now.date()}")print(f"时间: {now.time()}")# 格式化日期formatted = now.strftime("%Y年%m月%d日 %H:%M:%S")print(f"格式化后: {formatted}")

输出结果:

当前时间: 2026-01-30 17:07:30.442070日期: 2026-01-30时间: 17:07:30.442070格式化后: 2026年01月30日 17:07:30

2.math

使用 math 模块进行数学运算

import mathprint(f"π的值: {math.pi}")print(f"e的值: {math.e}")print(f"平方根: {math.sqrt(16)}")print(f"绝对值: {math.fabs(-10)}")

输出结果:

π的值: 3.141592653589793e的值: 2.718281828459045平方根: 4.0绝对值: 10.0

3.random

使用random模块生成随机数

import randomprint(f"随机整数: {random.randint(1, 100)}")print(f"随机浮点数: {random.random()}")print(f"随机选择: {random.choice(['苹果', '香蕉', '橙子'])}")

输出结果:

随机整数: 2随机浮点数: 0.6870458703638805随机选择: 苹果

4.os

使用os模块进行操作系统交互

import osprint(f"当前工作目录: {os.getcwd()}")print(f"当前目录文件列表: {os.listdir('.')}")print(f"环境变量PATH: {os.environ.get('PATH')}")

输出结果:

当前工作目录: D:\liudahua\pythonCode\python当前目录文件列表: ['calculator.py', 'main.py', '__pycache__']环境变量PATH: c:\Users\xx\AppData\Roaming\Code\User\globalStorage\xxx

除了 datetime、math、random、os 这些常用模块,Python 标准库包含了 200+ 个内置模块,涵盖了几乎所有基础功能。


三、包(Package)

3.1 什么是包?

包是包含多个模块的目录,每一个包需要包含一个特殊的 __init__.py 文件。

3.2 创建包的结构

my_package/├── __init__.py├── module1.py├── module2.py└── subpackage/    ├── __init__.py    └── module3.py

3.3 __init__.py 有什么作用呢?

情况 1:有 __init__.py

my_package/├── __init__.py└── module.py

引入包的几种方式:

import my_packageimport my_package.modulefrom my_package import module

全都正常, Python 会很清楚:my_package 是一个包。

情况 2:没有 __init__.py

my_folder/└── module.py

这样写会报错

import my_folder

必须要明确的导入那个文件。

import my_folder.module

而且有时能跑,有时不能(命名空间包的行为),不推荐这种写法。

在 Python 3.2 及以前的版本是必须要有的,没有 __init__.py 的目录不是包。Python 3.3+以后就是可选的了,因为引入了"命名空间包"(Namespace Package)。

3.4 包的使用示例

创建一个文件夹my_package,文件夹下面新增module1.py、module2.py 和 __init__.py文件。

module1.py 

# my_package/module1.pydef function1():    return "这是模块1的函数"def internal_function():    return "这是内部函数,不建议直接使用"

module2.py

# my_package/module2.pydef function2():    return "这是模块2的函数"

__init__.py

# my_package/__init__.pyprint("包初始化开始...")# 导入子模块的函数到包的命名空间from .module1 import function1from .module2 import function2__version__ = "1.0.0"__author__ = "Python学习者"print("包初始化完成!")

外部再创建一个 main.py 来使用这个包。

# 使用包import my_packageprint(my_package.function1())print(my_package.function2())print(f"包版本: {my_package.__version__}")

执行这个main.py

python `main.py

输出结果:

包初始化开始...包初始化完成!这是模块1的函数这是模块2的函数包版本: 1.0.0

可以看到,__init__.py 代码的优先级是最高的,非常适合做初始化工作。比如数据库连接、环境变量、组件注册等等。

四、常用内置模块

4.1 collections模块

下面的几个示例,先导入这行哈。

from collections import Counter, defaultdict, deque, namedtuple

Counter:计数器

text = "apple banana apple orange banana apple"word_count = Counter(text.split())print(f"单词统计: {word_count}")print(f"apple出现次数: {word_count['apple']}")

defaultdict:带默认值的字典

fruit_prices = defaultdict(lambda: 0.0)fruit_prices['apple'] = 5.0fruit_prices['banana'] = 3.0print(f"苹果价格: {fruit_prices['apple']}")print(f"橙子价格: {fruit_prices['orange']}")  # 返回默认值0.0,不会报错

deque:双端队列

queue = deque(['A', 'B', 'C'])queue.append('D')  # 右侧添加queue.appendleft('Z')  # 左侧添加print(f"队列: {queue}")print(f"弹出左侧: {queue.popleft()}")print(f"弹出右侧: {queue.pop()}")

namedtuple:命名元组

Point = namedtuple('Point', ['x', 'y'])p = Point(10, 20)print(f"点坐标: ({p.x}, {p.y})")

4.2 json模块

import json# Python对象转换为JSON字符串data = {    "name": "张三",    "age": 25,    "is_student": False,    "courses": ["Python", "数据结构", "算法"],    "address": {        "city": "北京",        "district": "海淀区"    }}json_str = json.dumps(data, ensure_ascii=False, indent=2)print("JSON字符串:")print(json_str)# 保存到文件with open("data.json", "w", encoding="utf-8") as f:    json.dump(data, f, ensure_ascii=False, indent=2)# 从JSON字符串解析json_data = '{"name": "李四", "age": 30}'parsed_data = json.loads(json_data)print(f"解析后的数据: {parsed_data}")print(f"姓名: {parsed_data['name']}")# 从文件读取with open("data.json", "r", encoding="utf-8") as f:    loaded_data = json.load(f)print(f"从文件加载: {loaded_data['name']}")

输出结果:

JSON字符串:{  "name": "张三",  "age": 25,  "is_student": false,  "courses": [    "Python",    "数据结构",    "算法"  ],  "address": {    "city": "北京",    "district": "海淀区"  }}解析后的数据: {'name': '李四', 'age': 30}姓名: 李四从文件加载: 张三

五、包管理

5.1 pip包管理工具

# 安装包pip install requestspip install pandas==1.5.0  # 指定版本pip install -r requirements.txt  # 从文件安装# 查看已安装的包pip listpip show requests  # 查看特定包信息# 升级包pip install --upgrade requests# 卸载包pip uninstall requests# 生成requirements.txtpip freeze > requirements.txt

5.2 requirements.txt示例

# 项目依赖文件requests==2.28.1pandas>=1.5.0numpy==1.23.5beautifulsoup4>=4.11.0flask>=2.2.0# 开发环境依赖pytest>=7.0.0black>=22.0.0flake8>=5.0.0

六、完整的项目结构示例

my_project/├── README.md           # 项目说明├── requirements.txt    # 依赖包列表├── .gitignore         # Git忽略文件├── src/               # 源代码目录│   ├── __init__.py│   ├── main.py        # 主程序│   ├── utils/         # 工具模块│   │   ├── __init__.py│   │   ├── file_utils.py│   │   └── math_utils.py│   ├── models/        # 数据模型│   │   ├── __init__.py│   │   └── user.py│   └── config.py      # 配置文件├── tests/             # 测试代码│   ├── __init__.py│   ├── test_utils.py│   └── test_models.py├── docs/              # 文档│   └── tutorial.md└── data/              # 数据文件    └── sample.json

今天的学习内容先到这里。如果有不对或者需要补充的地方,欢迎指正。

如果你觉得文章写的还不错,不妨点赞、推荐,转发给你的朋友看一下。

最新文章

随机文章