在python中导入模块的功能

时间:2015-03-09 09:39:56

标签: python

以下是3个模块,

point.py segment.py rectangle.py

其中rectangle.py模块从segment.py模块导入一个函数对象,如上所述,

from segment import get_size

# point.py
# Representation - start
from operator import sub, mul
from math import sqrt
#Constructor
def make_point(x, y):
    return (x, y)

#Selector
def x_coordinate(point):
    return point[0]

#Selector
def y_coordinate(point):
    return point[1]

#Selector
def distance_between_points(p1, p2):
    return sqrt(square(sub(p1[0],p2[0])) + square(sub(p1[1],p2[1])))

#helper for selector
def square(a):
    return mul(a, a)

#Representation - end

#Use - start

def get_x_coordinate(point):
    return x_coordinate(point)

def get_y_coordinate(point):
    return y_coordinate(point)

#Use - end

# segment.py
# Representation - start

from point import distance_between_points, make_point, get_x_coordinate, get_y_coordinate
#Constructor
def make_segment(point1, point2):
    return (point1, point2)

#Selector
def start_segment(lineSegment):
    return lineSegment[0]

#Selector
def end_segment(lineSegment):
    return lineSegment[1]

#Representation - end

#Use -start
def midpoint_segment(lineSegment):
    return make_point((get_x_coordinate(start_segment(lineSegment)) + get_x_coordinate(end_segment(lineSegment)))/2, (get_y_coordinate(start_segment(lineSegment)) + get_y_coordinate(end_segment(lineSegment)))/2)

def get_size(lineSegment):
    return distance_between_points(start_segment(lineSegment), end_segment(lineSegment))

#Use - end


#Driver code from user
p1 = make_point(1,2)
p2 = make_point(3, 4)
line = make_segment(p1, p2)
midpoint = midpoint_segment(line)
print(midpoint)

# rectangle.py
# Representation - start
from point import make_point, get_x_coordinate, get_y_coordinate
from segment import get_size
from operator import sub, abs
#Constructor
def make_rectangle(p1, p2, p3, p4):
    if are_opposite_sides_equal(p1, p2, p3, p4):
        return (p1, p2, p3, p4)

#Helper for constructor
def are_opposite_sides_equal(p1, p2, p3, p4):
    if (abs(sub(get_x_coordinate(p1), get_x_coordinate(p2))) == abs(sub(get_x_coordinate(p3), get_x_coordinate(p4)))) and (abs(sub(get_y_coordinate(p2), get_y_coordinate(p3))) == abs(sub(get_y_coordinate(p1), get_y_coordinate(p4)))):
        return True
    else:
        return False

#Selector
def get_length_side_segment(quadruple):
    return (quadruple[0], quadruple[1])

#Selector
def get_breadth_side_segment(quadruple):
    return (quadruple[1], quadruple[2])

#Representation - end


#Use -start
def perimeter(rectangle):
    segment1 = get_length_side_segment(rectangle)
    segment2 = get_breadth_side_segment(rectangle)
    length = get_size(segment1)
    breadth = get_size(segment2)
    return 2 * (length + breadth)

def area(rectangle):
    segment1 = get_length_side_segment(rectangle)
    segment2 = get_breadth_side_segment(rectangle)
    length = get_size(segment1)
    breadth = get_size(segment2)
    return (length * breadth)

#Use - end



#Driver code from user
p1 = make_point(1, 1)
p2 = make_point(3, 1)
p3 = make_point(3, 3)
p4 = make_point(1, 3)
rectangle = make_rectangle(p1, p2, p3, p4)
peri = perimeter(rectangle)
area_value = area(rectangle)

print(peri)
print(area_value)

我的问题:

根据rectangle.py的调试, 行from segment import get_size使segment.py的驱动程序代码执行并输出(2.0, 3.0)

我正在使用此声明来访问get_size。我想了解,函数对象的导入如何给出这个输出?

2 个答案:

答案 0 :(得分:2)

在python中导入模块基本上意味着您将它们作为脚本执行。即使您说import foofrom foo import bar,这种情况也会发生。 Python需要运行foo才能找到函数bar

在第一种情况下(import foo),您可以访问完整的命名空间,即您可以使用foo.getsize()foo.bar()或您的模块提供的任何函数,对象或其他内容。而在后一种情况下(from foo import bar),您只将函数bar导入当前命名空间,例如,您只能使用bar(),而不能使用getsize()

此外,有一种简单的方法可以让python执行模块的各个部分,当且仅当它作为主模块运行时,不是(如果它被导入)。例如,在segment.py中,您可以在脚本末尾写下以下内容:

def main()
    #Driver code from user
    p1 = make_point(1,2)
    p2 = make_point(3, 4)
    line = make_segment(p1, p2)
    midpoint = midpoint_segment(line)
    print(midpoint)

if __name__ == '__main__':
    main()

首先,我们定义一个main函数。如果语句main__name__ == '__main__',则此True函数仅 。这是什么意思?好吧,__name__是模块本身的固有变量。每次通过python segment.py运行模块或通过import segmentfrom segment import something导入模块时,此变量的设置都不同。

如果您通过python segment.py运行模块,则__name__等于字符串'__main__'。如果您导入模块,__name__将设置为模块的名称,此处为'segment'。因此,您可以轻松区分模块是作为主文件运行还是仅由其他文件导入。


编辑:

有关为什么from foo import bar需要完全执行foo的更多信息!?

如果Python没有执行foo,那么Python应该如何知道该模块包含函数bar? Python是一种解释型语言,因此函数和其他对象实际上只是在运行时从源代码创建的。

然而,Python非常聪明,只能一次执行您的脚本。因此,其他几个foo导入 - 即使在其他脚本中 - 也不需要重新执行您的模块,因为 foo 的命名空间已经建立。此行为在允许您在运行时自由修改任何模块/包(也来自其他人)方面具有一些优势。因此,如果你知道自己在做什么,你可以修补任何导入模块的功能和对象。这些修改可能会影响程序的整个范围(包括导入已修改库的所有其他模块和脚本)。 请注意,这通常是危险的,但有时会非常有帮助。

无论如何,THIS也可能是有用的阅读。

/ EDIT

答案 1 :(得分:0)

通过执行from something import somethingelse,您仍然导入something,然后只需将somethingelse添加到您的命名空间,以便something模块得到处理,这意味着您的顶级代码将会运行你是从打印

获得输出

如果您不希望不具备任何不属于类或函数声明的模块级代码