简体   繁体   English

在python中导入模块的功能

[英]Importing function of a module in python

Below are 3 modules, 以下是3个模块,

point.py segment.py rectangle.py , point.py segment.py rectangle.py

where rectangle.py module imports a function object from segment.py module as mentioned, 如上所述,其中rectangle.py模块从segment.py模块导入了一个功能对象,

from segment import get_size . 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)

My question: 我的问题:

As per the debugging of rectangle.py , line from segment import get_size makes the driver code of segment.py execute and give the output (2.0, 3.0) . 根据rectangle.py的调试, from segment import get_size的行使segment.py的驱动程序代码执行并给出输出(2.0, 3.0)

I am using this statement to get access to get_size . 我正在使用此语句来访问get_size I would like to understand, How an import of function object would give this output? 我想了解,导入函数对象将如何提供此输出?

Importing modules in python basically means you execute them as a script. 在python中导入模块基本上意味着您将其作为脚本执行。 This happens in both cases, even if you say import foo or from foo import bar . 即使您说import foofrom foo import bar ,这两种情况都会发生。 Python needs to run foo to be able to find the function bar . Python需要运行foo才能找到功能bar

In the first case ( import foo ) you have access to the full namespace, ie you could use foo.getsize() or foo.bar() or whatever functions, objects or whatnots your module provides. 在第一种情况下( import foo ),您可以访问完整的名称空间,即可以使用foo.getsize()foo.bar()或模块提供的任何函数,对象或其他功能。 Whereas in the latter case ( from foo import bar ) you import only the function bar into your current namespace, ie you could only use bar() , but not getsize() , for example. 而在后一种情况下( from foo import bar ),您仅将功能bar导入到当前名称空间中,即,例如,您只能使用bar() ,而不能使用getsize()

Furthermore, there is a simple way to make python execute parts of a module if and only if it is run as the main module and not if it is imported. 此外,有一种简单的方法可以使python当且仅当它作为主模块运行而不是导入时才执行模块的各个部分。 For instance, in segment.py , you could write the following at the end of the script: 例如,在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()

First of all, we define a main function. 首先,我们定义一个main功能。 This main function is only called if the statement __name__ == '__main__' is True . 当语句__name__ == '__main__'True 时才调用此main函数。 What does this mean? 这是什么意思? Well, __name__ is an inherent variable of the module itself. 好吧, __name__是模块本身的固有变量。 Every time the module is run via python segment.py or imported via import segment or via from segment import something , this variable is set differently. 每次模块通过python segment.py运行,或通过import segment或通过from segment import something ,此变量的设置都不同。

If you run the module via python segment.py , __name__ is equal to the string '__main__' . 如果通过python segment.py运行模块,则__name__等于字符串'__main__' If you import the module, __name__ is set to the name of the module, here 'segment' . 如果导入模块, __name__设置为模块的名称,此处为'segment' Thus, you can easily distinguish if a module is run as a main file or just imported by another file. 因此,您可以轻松地区分一个模块是作为主文件运行还是仅由另一个文件导入。


EDIT: 编辑:

More on why does from foo import bar needs to fully execute foo !? 为什么from foo import bar需要完全执行foo

If Python did not execute foo , how should Python know that the module contains the function bar ? 如果Python没有执行foo ,Python应该如何知道模块包含功能bar Python is an interpreted language, so functions and other objects are really only created from source during runtime. Python是一种解释型语言,因此功能和其他对象实际上仅是在运行时从源代码创建的。

However, Python is smart enough to execute your script only once . 但是,Python足够聪明,只需执行一次脚本即可 Thus, several other imports of foo - even in other scripts - do not require re-executing your module, because the namespace of foo is already established. 因此,其他几次foo导入(即使在其他脚本中)也不需要重新执行模块,因为foo的命名空间已经建立。 This behaviour has some advantages in terms of giving you freedom to modify any module/package (also from other people) during runtime. 就使您可以在运行时自由地修改任何模块/程序包(也可以从其他人那里)而言,此行为具有一些优势。 So if you know what you are doing, you can monkey-patch functions and objects of any imported module. 因此,如果您知道自己在做什么,则可以对任何导入模块的函数和对象进行猴子补丁。 These modifications can affect the whole scope of your program (including all other modules and scripts importing the modified library). 这些修改可能会影响程序的整个范围(包括导入修改后的库的所有其他模块和脚本)。 Note that this is often dangerous but from time to time incredibly helpful. 请注意,这通常很危险,但有时会非常有用。

Anyhow, THIS might also be a useful read. 无论如何, 可能也是有用的读物​​。

/EDIT . /编辑

by doing from something import somethingelse you still import something and then just add somethingelse to your namespace so the something module does get processed meaning your top level code will get run hence you are getting the output from print 通过from something import somethingelse您仍然会导入something ,然后仅向内容空间中添加somethingelse ,以便something模块确实得到处理,这意味着您的顶级代码将运行,因此您将从打印输出

if you don't want that don't have any module level code that is not a class or function declaration 如果您不希望没有任何不是类或函数声明的模块级代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM