从模块中导入并保留访问方式

3
标题可能有点难以理解,但我的问题很简单。我有一个程序需要对某个东西进行sqrt(),但这是我从math中唯一需要的功能。导入整个模块来获取单个函数似乎有点浪费。我可以使用“from math import sqrt”,但是那样会将sqrt()添加到我的程序主命名空间中,我不想要那样(特别是因为我计划修改程序以便作为模块可用;像那样导入会在那种情况下引起问题吗?)。是否有任何方法只导入该函数而仍保留math.sqrt()语法?在这个具体案例中,我使用Python 2.7,但如果Python 3有不同的答案,我也想听听以备将来参考。
4个回答

6
无论哪种方式,您都会以某种方式“导入”完整的math模块,因为它被编译并存储在sys.modules中。 因此,如果您使用from math import sqrtimport math,您都不会获得任何优化效益。 它们实际上是做完全相同的事情。 它们都导入整个math模块,将其存储在sys.modules中,然后唯一的区别在于第一个示例将sqrt函数引入命名空间,而第二个示例将math模块引入命名空间。 但是名称只是引用,因此仅从模块中导入一个对象并不会带来内存或CPU方面的好处。
如果您想要使用math.sqrt语法,则只需使用import math。 如果您想要sqrt()语法,则使用from math import sqrt
如果您担心保护您模块的用户免受污染他的命名空间(如果他执行星号导入:from your_module import *),则在您的模块中定义一个__all__变量,该变量是表示对象字符串列表,这些对象将在您模块的用户执行星号导入时被导入。

啊,我不知道那个。有用的信息。只是为了确定,py2exe 会改变这种情况吗? - Schilcote
不,py2exe不会改变Python导入模块的方式。 - Viktor Kerkez

1

使用math import sqrt。您可以使用__all__语句保护从模块导出的函数。 __all__应该是要从您的模块中导出的名称列表。


__all__ 只影响 from ... import *,而这种用法本来就不应该使用。 - user395760
是的,但他希望将他的程序作为模块提供给其他人使用。那么__all__是更好的选择,至少比免责声明“在使用此模块时不要使用import *”更可取。 - Hans Then
这可能有用,但是不要使用“import *”规则不应该在模块的文档中,而应该在样式指南和人们的头脑中。更重要的是,如果模块按照应该使用的方式使用,即使用“import module”或“from module import specific_thing”,那么您提出的解决方案并没有帮助。再说了,我甚至不确定是否存在问题。 - user395760
事实上,如果OP的用户按照您的建议只“import” OP的模块,则名称空间污染没有问题。我的建议是针对那些不按照您的建议使用“import”的OP用户的情况。 - Hans Then
我理解。我的观点是,在我看来,这种方式(import *)不是一个应该担心支持良好的用例,因为它通常是不鼓励的(参见每个样式指南),并且存在许多其他问题。 - user395760

0
不,这是不可能的,因为模块的工作方式。使用 import math 有什么问题吗?
考虑以下内容:

module.py

x = 1

def foo():
    return x

x = 2

def bar():
    returnx

主函数(伪代码):

import main but_only foo

print foo()

Python在遇到def foo这一行之前并不知道foo函数的存在。您提出的是从模块中随机选择行进行执行,但是Python如何知道应该选择哪些行呢?在这个例子中,foo()会返回什么值?

0
短答案是否定的。只需执行from math import sqrt即可。如果您将脚本用作模块,它不会引起任何问题,并且不会使代码变得不可读。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接