为什么在需要使用全名时导入?

kam*_*eto 9 python

在python中,如果您需要来自不同包的模块,则必须导入它.来自Java背景,这是有道理的.

import foo.bar
Run Code Online (Sandbox Code Playgroud)

什么是没有意义的,为什么每当我想使用酒吧时我需要使用全名?如果我想使用全名,为什么我需要导入?不使用全名立即描述我正在寻址的模块?

from foo import bar当这import foo.bar应该做什么时,似乎有点多余.当我打算使用全名时,为什么我必须导入也有点模糊.

Dav*_*d Z 23

问题是,即使Python的import声明看起来与Java类似,它们也会完全不同.如您所知,在Java中,import语句实际上只是对编译器的一个提示.它基本上为完全限定的类名设置别名.例如,当你写作

import java.util.Set;
Run Code Online (Sandbox Code Playgroud)

它告诉编译器,在整个文件中,当你写的时候Set,你的意思是java.util.Set.并且如果写s.add(o)在那里s是类型的对象Set,则编译器(或更确切地说,接头)熄灭并发现add方法中Set.class和在它的一个引用提出.

但在Python中,

import util.set
Run Code Online (Sandbox Code Playgroud)

(顺便说一下,这是一个制作模块)做了一些完全不同的事情.看看,在Python中,包和模块不仅仅是名称,它们是实际的对象,当您util.set在代码中编写时,它指示Python访问一个名为的对象util并在其上查找名为的属性set.Python import声明的工作是创建该对象和属性.它的工作方式是解释器查找名为的文件util/__init__.py,使用其中的代码定义对象的属性,并将该对象绑定到名称util.类似地,代码util/set.py用于初始化绑定的对象util.set.有一个函数调用__import__它来处理所有这些,事实上是声明import util.set 基本上相当于

util = __import__('util.set')
Run Code Online (Sandbox Code Playgroud)

关键是,当您导入Python模块时,您得到的是与顶级包对应的对象util.为了获得访问util.set你需要去通过,这就是为什么它似乎像你需要在Python中使用完全合格的名称.

当然,有办法解决这个问题.由于所有这些都是对象,一种简单的方法是绑定util.set到一个更简单的名称,即在import语句之后,你可以拥有

set = util.set
Run Code Online (Sandbox Code Playgroud)

从那时起你就可以使用set你本来写过的地方了util.set.(当然这会掩盖内置set类,所以我不建议实际使用该名称set.)或者,至少在另一个答案中提到,你可以写

from util import set
Run Code Online (Sandbox Code Playgroud)

要么

import util.set as set
Run Code Online (Sandbox Code Playgroud)

这仍然导入封装util与模块set中,但不是创建一个变量util在当前范围内,它会创建一个变量set引用util.set.在幕后,这有点像

_util = __import__('util', fromlist='set')
set = _util.set
del _util
Run Code Online (Sandbox Code Playgroud)

在前一种情况下,或

_util = __import__('util.set')
set = _util.set
del _util
Run Code Online (Sandbox Code Playgroud)

在后者中(尽管两种方式基本上都是一样的).这种形式在语义上更像Java的import声明所做的:它将别名(set)定义为通常只能由完全限定名称(util.set)访问的内容.


Don*_*ner 6

如果您愿意,可以缩短它:

import foo.bar as whateveriwant
Run Code Online (Sandbox Code Playgroud)

使用全名可防止具有相同名称子模块的两个包相互冲突.

  • 它接近正确的答案,但没有解释*为什么*Python表现出这种行为. (3认同)
  • @Martin Beckett:只有`bar`是一个模块.当b是方法或变量时,`import ab as c`语法不起作用.实际上,无论如何都不能使用点表示法导入方法或变量.您必须使用`from ... import ...`语法,或通过包含模块名称引用方法或变量. (2认同)