Python3 内置变量¶

Python3 内置变量¶

Python 中有一些特殊的内置变量(也称为魔术变量或特殊变量),它们以双下划线开头和结尾。这些变量在 Python 的运行时环境中具有特殊含义和功能。

name 和 main¶

name 变量¶

__name__ 是 Python 中的一个特殊变量,用于判断当前模块是被直接运行还是被导入。

基本概念¶

# 创建一个文件 test_module.py

print(f"__name__ 的值是: {__name__}")

def hello():

print("Hello from test_module!")

if __name__ == "__main__":

print("这个文件被直接运行")

hello()

else:

print("这个文件被导入为模块")

直接运行 vs 导入¶

# 直接运行 test_module.py

# 输出:

# __name__ 的值是: __main__

# 这个文件被直接运行

# Hello from test_module!

# 在另一个文件中导入

import test_module

# 输出:

# __name__ 的值是: test_module

# 这个文件被导入为模块

实际应用示例¶

# calculator.py

def add(a, b):

return a + b

def subtract(a, b):

return a - b

def multiply(a, b):

return a * b

def divide(a, b):

if b == 0:

raise ValueError("除数不能为零")

return a / b

# 测试代码 - 只在直接运行时执行

if __name__ == "__main__":

print("计算器测试")

print(f"5 + 3 = {add(5, 3)}")

print(f"5 - 3 = {subtract(5, 3)}")

print(f"5 * 3 = {multiply(5, 3)}")

print(f"6 / 3 = {divide(6, 3)}")

# main.py

import calculator

print("使用计算器模块")

print(f"10 + 20 = {calculator.add(10, 20)}")

print(f"10 - 5 = {calculator.subtract(10, 5)}")

main 的用途¶

模块测试:为模块提供独立的测试代码

程序入口:作为 Python 程序的入口点

避免重复执行:防止导入时执行不必要的代码

file¶

__file__ 变量包含当前文件的路径。

# file_demo.py

import os

print(f"当前文件路径: {__file__}")

print(f"文件名: {os.path.basename(__file__)}")

print(f"目录名: {os.path.dirname(__file__)}")

print(f"绝对路径: {os.path.abspath(__file__)}")

# 构建相对路径

current_dir = os.path.dirname(os.path.abspath(__file__))

config_path = os.path.join(current_dir, 'config.json')

print(f"配置文件路径: {config_path}")

doc¶

__doc__ 变量包含模块、类或函数的文档字符串。

# doc_demo.py

"""

这是一个示例模块,展示 __doc__ 变量的使用。

这个模块包含了各种示例函数和类,用于演示文档字符串的用法。

"""

class Calculator:

"""简单的计算器类"""

def add(self, a, b):

"""加法运算

Args:

a (int/float): 第一个数

b (int/float): 第二个数

Returns:

int/float: 两数之和

"""

return a + b

def multiply(a, b):

"""乘法函数

Args:

a (int/float): 被乘数

b (int/float): 乘数

Returns:

int/float: 乘积

"""

return a * b

# 访问文档字符串

if __name__ == "__main__":

print("模块文档:")

print(__doc__)

print("\n类文档:")

print(Calculator.__doc__)

print("\n方法文档:")

print(Calculator.add.__doc__)

print("\n函数文档:")

print(multiply.__doc__)

package¶

__package__ 变量指示模块所属的包。

# 在包结构中

# my_package/__init__.py

print(f"包的 __package__: {__package__}") # None

# my_package/module.py

print(f"模块的 __package__: {__package__}") # my_package

version¶

虽然不是内置变量,但常用于版本控制。

# my_module.py

__version__ = "1.0.0"

__author__ = "张三"

__email__ = "zhangsan@example.com"

def get_version():

return __version__

def get_module_info():

return {

'version': __version__,

'author': __author__,

'email': __email__

}

all¶

__all__ 变量定义模块的公共接口。

# my_module.py

__all__ = ['public_function', 'PublicClass']

def public_function():

"""公共函数"""

return "这是公共函数"

def _private_function():

"""私有函数"""

return "这是私有函数"

class PublicClass:

"""公共类"""

pass

class _PrivateClass:

"""私有类"""

pass

# 当使用 from my_module import * 时,只会导入 __all__ 中定义的内容

import (函数)¶

__import__ 是一个内置函数,用于动态导入模块。

# dynamic_import.py

def dynamic_import_module(module_name):

"""动态导入模块"""

try:

module = __import__(module_name)

print(f"成功导入模块: {module_name}")

return module

except ImportError as e:

print(f"导入模块失败: {module_name}, 错误: {e}")

return None

# 使用示例

if __name__ == "__main__":

# 导入标准库模块

math_module = dynamic_import_module('math')

if math_module:

print(f"π 的值: {math_module.pi}")

# 尝试导入不存在的模块

dynamic_import_module('nonexistent_module')

builtins¶

__builtins__ 变量包含所有内置函数和异常。

# builtins_demo.py

import builtins

def show_builtins_info():

"""显示内置函数信息"""

print("部分内置函数:")

builtin_functions = [name for name in dir(builtins)

if not name.startswith('_') and callable(getattr(builtins, name))]

for func in sorted(builtin_functions)[:10]: # 显示前10个

print(f"- {func}")

print(f"\n总共有 {len(builtin_functions)} 个内置函数")

# 自定义 print 函数

original_print = builtins.print

def custom_print(*args, **kwargs):

"""自定义打印函数,添加前缀"""

original_print("[自定义]", *args, **kwargs)

if __name__ == "__main__":

show_builtins_info()

# 临时替换内置 print 函数

builtins.print = custom_print

print("这是使用自定义 print 函数")

# 恢复原始 print 函数

builtins.print = original_print

print("这是使用原始 print 函数")

path¶

__path__ 变量用于包的搜索路径。

# my_package/__init__.py

print(f"包的搜索路径: {__path__}")

annotations¶

__annotations__ 变量包含函数参数和返回值的类型注解。

# annotations_demo.py

def greet(name: str, age: int = 25) -> str:

"""问候函数"""

return f"Hello, {name}! You are {age} years old."

def calculate(a: float, b: float) -> float:

"""计算函数"""

return a + b

if __name__ == "__main__":

print("greet 函数的注解:")

print(greet.__annotations__)

print("\ncalculate 函数的注解:")

print(calculate.__annotations__)

debug¶

__debug__ 变量指示 Python 是否在调试模式下运行。

# debug_demo.py

def debug_function():

"""调试函数"""

if __debug__:

print("调试模式:执行额外的检查")

# 执行一些调试相关的操作

else:

print("非调试模式:跳过调试操作")

def optimize_function():

"""优化函数"""

if __debug__:

# 调试模式下的代码

print("执行完整的验证逻辑")

# 复杂的验证代码

else:

# 优化后的代码

print("执行优化后的逻辑")

if __name__ == "__main__":

print(f"当前调试模式: {__debug__}")

debug_function()

optimize_function()

print("\n使用 -O 选项运行时,__debug__ 将为 False")

loader¶

__loader__ 变量指示用于加载模块的加载器。

# loader_demo.py

import sys

def show_loader_info():

"""显示加载器信息"""

if hasattr(__loader__, 'name'):

print(f"加载器名称: {__loader__.name}")

else:

print(f"加载器类型: {type(__loader__)}")

print(f"加载器: {__loader__}")

if __name__ == "__main__":

show_loader_info()

spec¶

__spec__ 变量包含模块的导入系统规范。

# spec_demo.py

def show_module_spec():

"""显示模块规范信息"""

if __spec__ is not None:

print(f"模块名称: {__spec__.name}")

print(f"模块文件: {__spec__.origin}")

print(f"是否有子模块: {__spec__.submodule_search_locations}")

print(f"加载器: {__spec__.loader}")

else:

print("没有模块规范信息")

if __name__ == "__main__":

show_module_spec()

实际应用示例¶

1. 命令行工具模板¶

# cli_tool.py

import argparse

import sys

from pathlib import Path

__version__ = "1.0.0"

__author__ = "开发者"

__description__ = "一个简单的命令行工具"

def create_parser():

"""创建命令行参数解析器"""

parser = argparse.ArgumentParser(

description=__description__,

prog=Path(__file__).stem

)

parser.add_argument(

'--version',

action='version',

version=f'%(prog)s {__version__}'

)

parser.add_argument(

'--verbose', '-v',

action='store_true',

help='详细输出'

)

parser.add_argument(

'input_file',

help='输入文件路径'

)

return parser

def main():

"""主函数"""

parser = create_parser()

args = parser.parse_args()

if args.verbose:

print(f"当前文件: {__file__}")

print(f"模块名称: {__name__}")

print(f"版本: {__version__}")

print(f"处理文件: {args.input_file}")

if __name__ == "__main__":

main()

else:

print(f"模块 {__name__} 已导入,版本 {__version__}")

2. 配置管理模块¶

# config.py

import os

import json

from pathlib import Path

__config__ = {}

def load_config(config_file=None):

"""加载配置文件"""

if config_file is None:

# 使用当前目录下的 config.json

current_dir = Path(__file__).parent

config_file = current_dir / 'config.json'

if config_file.exists():

with open(config_file, 'r', encoding='utf-8') as f:

__config__.update(json.load(f))

print(f"配置已加载: {config_file}")

else:

print(f"配置文件不存在: {config_file}")

__config__ = get_default_config()

def get_default_config():

"""获取默认配置"""

return {

'debug': False,

'timeout': 30,

'max_retries': 3,

'database': {

'host': 'localhost',

'port': 5432

}

}

def get_config(key=None, default=None):

"""获取配置值"""

if key is None:

return __config__

return __config__.get(key, default)

# 模块加载时自动加载配置

if __name__ == "__main__":

# 作为主程序运行时

load_config()

print("当前配置:", get_config())

else:

# 作为模块导入时

print(f"配置模块已加载 (从 {__name__})")

3. 日志配置模块¶

# logger.py

import logging

import sys

from pathlib import Path

__loggers__ = {}

def setup_logger(name=None, level=logging.INFO, log_file=None):

"""设置日志器"""

if name is None:

name = Path(__file__).stem

if name in __loggers__:

return __loggers__[name]

logger = logging.getLogger(name)

logger.setLevel(level)

# 控制台处理器

console_handler = logging.StreamHandler(sys.stdout)

console_handler.setLevel(level)

# 文件处理器

if log_file:

file_handler = logging.FileHandler(log_file, encoding='utf-8')

file_handler.setLevel(level)

logger.addHandler(file_handler)

# 格式化器

formatter = logging.Formatter(

'%(asctime)s - %(name)s - %(levelname)s - %(message)s'

)

console_handler.setFormatter(formatter)

if log_file:

file_handler.setFormatter(formatter)

logger.addHandler(console_handler)

__loggers__[name] = logger

return logger

def get_logger(name=None):

"""获取日志器"""

if name is None:

name = Path(__file__).stem

return __loggers__.get(name, setup_logger(name))

# 模块级别的日志器

logger = get_logger()

if __name__ == "__main__":

# 测试日志功能

logger.info(f"日志模块测试 (文件: {__file__})")

logger.debug("调试信息")

logger.warning("警告信息")

logger.error("错误信息")

最佳实践¶

1. 模块结构¶

# module_template.py

"""

模块文档字符串

这个模块提供了...功能。

"""

# 模块元信息

__version__ = "1.0.0"

__author__ = "作者名"

__email__ = "author@example.com"

__license__ = "MIT"

__description__ = "模块描述"

# 公共接口

__all__ = ['public_function', 'PublicClass']

# 导入依赖

import os

import sys

from typing import Any, List

# 私有变量

_private_var = "这是一个私有变量"

# 公共函数

def public_function():

"""公共函数"""

return "Hello, World!"

def _private_function():

"""私有函数"""

return "This is private"

# 类定义

class PublicClass:

"""公共类"""

pass

class _PrivateClass:

"""私有类"""

pass

# 模块初始化代码

if __name__ == "__main__":

# 模块测试代码

print(f"模块 {__name__} 版本 {__version__}")

print("模块测试:")

print(public_function())

else:

# 模块被导入时的初始化

logger = get_logger(__name__)

logger.info(f"模块 {__name__} 已加载")

2. 版本检查¶

# version_check.py

def check_python_version(min_version=(3, 8)):

"""检查 Python 版本"""

current_version = sys.version_info[:2]

if current_version < min_version:

raise RuntimeError(

f"需要 Python {min_version[0]}.{min_version[1]} 或更高版本,"

f"当前版本: {current_version[0]}.{current_version[1]}"

)

print(f"Python 版本检查通过: {current_version[0]}.{current_version[1]}")

if __name__ == "__main__":

check_python_version()