1

Below are 3 modules,

point.py segment.py rectangle.py,

where rectangle.py module imports a function object from segment.py module as mentioned,

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).

I am using this statement to get access to get_size. I would like to understand, How an import of function object would give this output?

3
  • 1
    When you import a module it executes the statements in it. Commented Mar 9, 2015 at 9:46
  • @PeterWood when I say, from segment import get_size Am I importing just a function get_size of module segment or the complete module segment? Because I do not have access to other functions of module segment in module rectangle Commented Mar 9, 2015 at 9:48
  • 1
    If you do not want that code executed, you should put it under if __name__ == "__main__": Commented Mar 9, 2015 at 9:48

2 Answers 2

2

Importing modules in python basically means you execute them as a script. This happens in both cases, even if you say import foo or from foo import bar. Python needs to run foo to be able to find the function bar.

In the first case (import foo) you have access to the full namespace, i.e. you could use foo.getsize() or foo.bar() or whatever functions, objects or whatnots your module provides. Whereas in the latter case (from foo import bar) you import only the function bar into your current namespace, i.e. you could only use bar(), but not getsize(), for example.

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. For instance, in segment.py, you could write the following at the end of the script:

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. This main function is only called if the statement __name__ == '__main__' is True. What does this mean? Well, __name__ is an inherent variable of the module itself. 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.

If you run the module via python segment.py, __name__ is equal to the string '__main__'. If you import the module, __name__ is set to the name of the module, here '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!?

If Python did not execute foo, how should Python know that the module contains the function bar? Python is an interpreted language, so functions and other objects are really only created from source during runtime.

However, Python is smart enough to execute your script only once. 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. 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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

if you don't want that don't have any module level code that is not a class or function declaration

9 Comments

what is the difference between import segment and from segment import get_size?
@overexchange the former will give you the name segment to use, the later will give you the name get_size to use. Both however will execute the segment module if it is the first time it has been imported by your system.
@PeterWood "Both however will execute"? this is not convincing syntax.Because it is breaking the purpose because am saying import get_size but not import segment
But how should python know that your module actually contains a function called get_size if it does not execute the script? Python cannot partially execute segment.py only containing the function you need. Think about it, what would happen in the case your function get_size actually depends on many other functions in segment.py?
@overexchange You are saying you want to use things from the segment module. Python will load that module into memory and execute it. This defines any functions, variables, classes, etc, and also calls any other statements in the top level of the module. Then the functions, etc, will be available to you to import. If you want the whole module you say import segment if you only want segment.get_size, and don't want to have to call it as segment.get_size() you can give it a local name from segment import get_size. This lets you call it as get_size().
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.