You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何导入可触发函数执行、无需用户实例化类的变量

实现方案

方案1:Python 3.7+ 模块__getattr__实现(最简方案)

Python 3.7及以上版本支持模块级别的__getattr__方法,当访问模块中不存在的属性时会自动触发该方法,我们可以用这个特性实现变量访问时的自动逻辑注入,全程对调用方透明。
改写后的mnist.py代码如下:

import os
# 按需引入你的下载逻辑依赖,比如requests

# 私有变量缓存已加载的内容,避免重复执行逻辑
_images = None
_labels = None

def _check_and_download(file_path):
    """自定义文件校验、下载逻辑,可根据实际需求修改"""
    if not os.path.exists(file_path):
        print(f"文件{file_path}不存在,正在下载...")
        # 此处补充你的下载、存储逻辑
    # 下载完成后读取文件内容返回,下方为示例返回值
    return f"{file_path}的实际内容"

def __getattr__(name):
    global _images, _labels
    if name == "images":
        if _images is None:
            _images = _check_and_download("./mnist_images.npy")
        return _images
    elif name == "labels":
        if _labels is None:
            _labels = _check_and_download("./mnist_labels.npy")
        return _labels
    elif name == "show":
        def show():
            print("Im showing your image")
        return show
    raise AttributeError(f"module {__name__} has no attribute {name}")

调用方run.py代码完全不需要修改,和原有写法完全一致:

from examples.mnist import images, labels, show

print(images)
print(labels)
show()

第一次访问images/labels时会自动执行检查、下载逻辑,后续访问会直接返回已经加载好的缓存值,不会重复执行逻辑。

方案2:兼容全Python版本的模块实例替换方案

如果需要兼容Python 3.7以下版本,可以将当前模块对象替换为一个带属性getter的类实例,实现同样的效果:
改写后的mnist.py代码如下:

import os
import sys

class _MNISTModule:
    def __init__(self):
        self._images = None
        self._labels = None
    
    def _check_and_download(self, file_path):
        """和方案1的校验、下载逻辑完全一致"""
        if not os.path.exists(file_path):
            print(f"文件{file_path}不存在,正在下载...")
            # 下载逻辑略
        return f"{file_path}的实际内容"
    
    @property
    def images(self):
        if self._images is None:
            self._images = self._check_and_download("./mnist_images.npy")
        return self._images
    
    @property
    def labels(self):
        if self._labels is None:
            self._labels = self._check_and_download("./mnist_labels.npy")
        return self._labels
    
    def show(self):
        print("Im showing your image")

# 把当前模块替换为类实例,用户导入时拿到的就是该实例
sys.modules[__name__] = _MNISTModule()

调用方代码同样不需要做任何修改,使用体验和普通模块变量完全一致。

内容的提问来源于stack exchange,提问作者Daniel Wilczak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 08:54:03