Python 导入机制 [英] Python import mechanics

查看:30
本文介绍了Python 导入机制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个相关的 Python 'import' 问题.它们很容易测试,但我想要语言定义的而不是特定于实现的答案,而且我也对样式/约定感兴趣,所以我在这里问.

1)

如果模块 A 导入模块 B,模块 B 导入模块 C,模块 A 中的代码是否可以在没有显式导入的情况下引用模块 C?如果是这样,我认为这是不好的做法是否正确?

2)

如果我导入模块 A.B.C,那是否也导入模块 A 和 A.B?如果是这样,按照约定是否更好地显式 import A;进口A.B;导入 A.B.C?

解决方案

您应该知道的第一件事是 Python 语言不是 ISO 标准.这与 C/C++ 有很大不同,这意味着没有正确"的方式来定义语言行为——CPython 可能会做某事,因为它是这样编码的,而 Jython 可能会做相反的事情.

关于您的问题,请记住导入"模块是一个由两部分组成的操作:首先加载模块 - 如果它从未加载过,例如如果它在 sys.modules 中不可用,则名称将绑定到本地命名空间中的该模块.

因此:

1) 是的,您可以通过提供适当的命名空间来从模块 a 中引用任何您想要的内容,例如你必须做类似的事情

B.C.name = "某物"

而且我认为这在 Python 程序中很少完成,并且可能被认为是不好的做法,因为它强制执行可传递的 dep"——如果某个模块 B 实现被重构并且不再依赖于 C,它应该继续提供C模块只是为了满足A deps.

当然设置 __ all __ 可以防止这种情况发生,一个好的做法可能是将 __ all __ 放在所有模块中,并导出你想要真正公开的符号.>

2) 是和否.做

导入 a.b.c.d

在所有模块上执行第一个导入阶段(加载),但第二个只是在 a(并且,递归地,在 b 中,相对于 c 等),但链中的所有模块必须被完整的命名空间引用;这样导入后,你可以做

a.somethinga.b.某事a.b.c.某事

但是你做不到

c.somethingb. 某物

我必须承认这种用法也很少见;我通常更喜欢从模块导入一些东西"的导入方式,通常你只需要询问你需要的东西——这种嵌套在库中既不常见,也不常见.

很多时候有外部包",仅用于组织,其中包含带有类的模块.很可能上面的a、b、c只是包,而d是一个真正包含类、函数和其他对象的模块.所以正确的用法是:

from a.b.c.d import name1, name2, name3

我希望这能满足您的好奇心.

I have two related Python 'import' questions. They are easily testable, but I want answers that are language-defined and not implementation-specific, and I'm also interested in style/convention, so I'm asking here instead.

1)

If module A imports module B, and module B imports module C, can code in module A reference module C without an explicit import? If so, am I correct in assuming this is bad practice?

2)

If I import module A.B.C, does that import modules A and A.B as well? If so, is it by convention better to explicitly import A; import A.B; import A.B.C?

解决方案

The first thing you should know is that the Python language is NOT an ISO standard. This is rather different from C/C++, and it means that there's no "proper" way to define a language behaviour - CPython might do something just because it was coded that way, and Jython might do the other way round.

about your questions, remember that "importing" a module is a two-part operation: first the module is loaded - if it had never been, e.g. if it wasn't available in sys.modules, then a name is bound to that module in the local namespace.

hence:

1) Yes, you can reference whatever you want from module a by providing the proper namespace, e.g. you'll have to do something like

B.C.name = "something"

And I think this is very rarely done in Python programs and could be considered bad practice since it forces a "transitive dep" - if some module B implementation is refactored and doesn't depend on C anymore, it should continue offering the C module just for satisfying A deps.

Of course setting __ all __ can prevent this, and a good practice may be to put __ all __ in all your modules, and export just the symbols you want to be really public.

2) Yes and no. Doing

import a.b.c.d 

performs the first import phase (loading) on all modules, but the second just on a (and, recursively, in b with respect to c, etc) but all the modules in the chain must be referenced by full namespace; after such an import, you can do

a.something
a.b.something
a.b.c.something

but you can't do

c.something
b.something

I must admit that kind of usage is pretty rare as well; I generally prefer the "from module import something" way-to-import, and generally you just ask for what you need - such nesting is neither common in libraries, nor its usage is that common.

Many times there're "outer packages", just used for organization, which hold modules with classes. It's very likely that a, b, c above are just packages, and d is a module which truly holds classes, functions and other objects. So the proper usage would be:

from a.b.c.d import name1, name2, name3

I hope this satifies your curiosity.

这篇关于Python 导入机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆