Python中的自动加载

15 投票
3 回答
7443 浏览
提问于 2025-04-15 12:24

过去我用过Perl的AUTOLOAD功能来实现懒加载,也就是在需要的时候才把符号加载到命名空间里。我想在Python中也实现类似的功能。

通常,最接近的做法是使用一个类和一个__getattr__方法来达到这个效果。不过我也试着在sys.modules里翻找,最后得到了这个:

# mymod.py
def greet(greeting="Hello World"):
   print greeting

class Autoload(object):
    def __init__(self, __name__):
        super(Autoload, self).__init__()
        self.wrapped_name = __name__
        self.wrapped = sys.modules[__name__]
    def __getattr__(self, name):
        try:
            return getattr(self.wrapped, name)
        except AttributeError:
            def f():
                greet(name+" "+self.wrapped_name)
            return f

if __name__ != "__main__":
    import sys
    sys.modules[__name__] = autoload(__name__)

从用户的角度来看,这个方法确实能按照我想要的方式工作:

~> python
Python 2.5.1 (r251:54863, Jan 10 2008, 18:01:57)
[GCC 4.2.1 (SUSE Linux)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mymod
>>> mymod.hello()
hello mymod
>>> from mymod import Hello_World
>>> Hello_World()
Hello_World mymod

但我在想,Python中有没有人们通常使用的标准方法来实现自动加载呢?

其次,想问问有经验的Python开发者,这种做法是好是坏?我算是有点经验的Python开发者,我觉得这个方法挺有用的,但又觉得有点边缘,所以想知道这是否可以被视为好习惯、坏习惯或者其他。

3 个回答

-1

不,我觉得这样做没什么用。

为什么要为你想从模块中获取的每一个属性都创建一个函数呢?这听起来很让人困惑。感觉就像是有些新函数是凭空出现的,所以你得深入了解实现细节才能明白发生了什么。而这一切都没有带来任何语法上的好处。

即使你有很好的理由这样做,为什么还要用模块呢?为什么要把你的类实例注册到sys.modules里?在Python中,让事物看起来不是它们本来的样子是被不赞成的。

除非你是故意让代码变得复杂,否则我看不出这样做的理由。

10

“懒加载导入”可以建立在PEP 302中指定的“导入钩子”之上,这个功能现在已经完全实现。之前PEP 369涵盖了“懒加载导入”和导入后的钩子,但现在已经简化,只讨论导入后的钩子;不过,你可能会对最初的草案感兴趣。

通过meta_path钩子实现的“懒加载导入”的一个不错的例子可以在这个链接中找到。

2

关于用类来模拟模块的问题:

没错,这种功能并不是偶然出现的。从2.x版本早期就有这个功能,并且在3.x版本中也依然有效。

关于懒加载的问题:

有好几种方法可以实现懒加载,每种方法都有点神秘。使用模块模拟器是一种不错的方法。

撰写回答