了解导入和范围

时间:2017-04-18 02:38:35

标签: python python-3.x python-import python-3.6

我是python的菜鸟,我想了解import语句的工作原理。

我正在运行python 3.6。 我有空闲工作。

我的测试目录设置为

目录:test_py

在目录test_py中我有文件 test_calc.py,button.py,graphics.py

graphics.py是一个图形库。

我的主程序是 test_calc.py

test_calc.py 中,我使用 from graphics import * 。它的第一行

button.py是一个包含类定义Button的模块。 它还使用图形库graphics.py。

test_calc.py中的主程序使用Button类。 Button类定义还调用Point,这是图形库中的一个函数。

我认为创建Button对象的调用将能够使用graphcs 来自test_calc.py中语句来自图形导入* 的库,但它不能。

button.py还需要 from graphics import * 来访问图形库函数。

我有没有办法在test_calc.py中使用图形导入* **中的** 并让Button类也看到图形库 模块和对象,而不必在button.py?

中导入它

我花了很多时间阅读8小时并尝试解决这个问题。 任何帮助表示赞赏。

这是完整的test_calc.py文件

from graphics import *
from button import *

def __createButtons(win):
    #create a list of buttons
    bSpecs = [(2,1,'0'), (3,1,'.'),
              (1,2,'1'), (2,2,'2'), (3,2,'3'), (4,2,'+'), (5,2,'-'),
              (1,3,'4'), (2,3,'5'), (3,3,'6'), (4,3,'*'), (5,3,'/'),
              (1,4,'7'), (2,4,'8'), (3,4,'9'), (4,4,'<-'), (5,4,'C')] 

buttons = []

for (cx,cy,label) in bSpecs:
    buttons.append(Button(win, Point(cx,cy), .75,.75,label))

###create larger = button
buttons.append(Button(win, Point(4.5,1), 1.75, .75, "="))

#activate all buttons
for b in buttons:
    b.activate()

def main():
    #create the window for the calculator
    win = GraphWin("Calculator")
    win.setCoords(0,0,6,7)
    win.setBackground("slategray")
    win= win
    __createButtons(win)

main()

这是button.py

的开头

没有此声明的按钮无法使用图形库中的Point函数

from graphics import * 
class Button:

def __init__(self, win, center, width, height, label):
        w,h = width/2.0, height/2.0
        x,y = center.getX(), center.getY()
        self.xmax, self.xmin = x+w, x-w
        self.ymax, self.ymin = y+h, y-h

        #Point function from graphics library
        p1 = Point(self.xmin,self.ymin)
        p2 = Point(self.xmax, self.ymax)

2 个答案:

答案 0 :(得分:0)

简短回答:不,没有办法做到这一点。

graphics.py超出了button.py的范围,因为test_calc.py导入的图片和test_calc.pybutton.py的范围内。

但是,如果您确实要保存额外的行,则可以从from graphics import *删除test_calc.py,因为button.py已导入graphics.py

答案 1 :(得分:0)

不,你不能这样做。如果按照您希望的方式工作,您将在button内隐式地打破命名空间和范围,而不仅仅是test_calc中的明确命中。

模块的范围(由该模块中定义的所有内容使用)由它导入的内容及其定义的内容(以及在设计不良的情况下,由后来的Monkey = patched)定义。从“导入我的东西中定义的内容”中添加内容是一个糟糕的主意。

这里的正确解决方案就是:

# If a package, explicit relative imports avoid checking the whole of sys.path
from .graphics import *

# IF not a package, use plain names without leading .s
from graphics import *

位于button.py文件的顶部,因此它实际指定了从中获取API的位置(理想情况下,您明确列出要使用的名称,而不仅仅是*,这有助于静态检查代码确定是否定义了所有名称,帮助维护者找出特定名称的来源,并避免两个模块提供相同名称并相互踩踏的风险。既然你已经做到了,那你就是金色的;您可以在graphics中省略test_calc.py内容的导入(假设test_calc.py本身不使用它)。

如果出于某些疯狂的原因,这确实是必要的,最简单的方法是绕过import语义并明确eval button的代码在同一范围内{包括graphics内容。在test_calc.py之后,在from graphics import *之后,您明确openread button.py的内容(例如,button_source)然后做:

eval(compile(button_source, button_path, 'exec'), globals())

将使用button.py的全局范围(现在包括test_calc内容)编译和评估graphics的源代码,因此新定义的内容将在{{ 1}}的全局变量,并将那里定义的所有东西看作是它的“原生范围”。