Then, the print sleep function call displays REM.
Then, the import statement rebinds sleep to the sleep function from the time module.
The function call to sleep works as intended.
When the condition of the if statement is evaluated,
the identifier sleep is dereferenced to obtain the sleep function object,
which is not equal to the string REM even though the user input the REM string.
There is still a name conflict and program output is incorrect.
You can resolve a name conflict by selecting
a different identifier to bind to one of the conflicting objects.
I could bind a different identifier to the input string such as
sleep mode and keep the identifier sleep for the imported sleep function.
I need to change sleep to sleep mode
everywhere I want to refer to the string that was entered by the user.
In this case, sleep mode may be more descriptive identifier for the input string.
However, in a program called sleep,
that is about the topic of sleep,
using the name sleep as the name of the function is not very descriptive.
Python provides the versatility to resolve conflicts due to
imported names using different variations of the import statement.
These variations allow you to use
the most appropriate local name in your program to represent each imported object.
You were not constrained by the names used in other modules.
Here is a generalization of our previous import statement that adds an optional
as clause to provide an alternate local name for each imported name.
This local name is often called an alias.
I will go back to using sleep instead of sleep mode to refer to the input string.
I will use this new variation of the imported statement to change
the imported local name from sleep to pause which is more descriptive in this program.
The program output is correct.
Here are the generalized semantics of the import statement.
When the program starts,
the main module namespace contains the identifier as input and print,
each bound to a function object.
When the import statement is evaluated,
the identifier pause is added to the namespace
and bound to the sleep function object from the time module.
Next, the input function returns
a REM string object and
the assignment statement binds the sleep identifier to this object.
The print function call displays the string object.
The next statement is a function call whose function name is pause.
The interpreter dereferences the pause identifier to obtain a function object.
So, the program continues as intended.
The name conflict has been eliminated.
Another variation of the import statement does not use the keyword from.
Here's a new syntax diagram for the import statement that
supports both the from variation that you have already seen,
and the new non-from variation.
Here's the from variation you have already seen.
Here is a syntax diagram for the new non-from variation.
If this new variation is used,
then when an identifier from an imported module is used,
it must be used as an attribute of that module.
For example, here's a version of the sleep program that uses this variation.
The program output is correct.
Here are the semantics of the non-from variation of the import statement.
When the program starts,
the main module namespace contains the identifier as input and print,
each bound to a function object.
When the import statement is evaluated,
the identifier time is added to the namespace and bound to the time module object.
None of the identifiers in the time module are bound in the main modules namespace,
just the name of the module itself.
Next, the input function returns
a REM string object and
the assignment statement binds the sleep identifier to this object.
The print function call displays this string object.
The next statement is a function call whose function name is time.sleep.
This is an attribute reference.
An attribute reference is necessary because
only the module name is in the main module's namespace.
The name of the sleep function is not.
Recall the syntax and semantics of attribute reference from the method calls lesson.
First, the interpreter evaluates the expression time to obtain an object.
In this case, it is the time module object.
Second, the interpreter checks if
the attribute sleep is in the namespace of the time module object.
Since sleep is a function defined in the time module,
sleep is in time's namespace.
So, the sleep function object is obtained.
The interpreter applies this function to the argument list,
which is a single Integer object one and the sleep function pauses for one second.
The program continues as intended.
The name conflict has been eliminated.
In Python, modules can be defined inside of other modules.
A module inside another module is called a submodule.
To import objects from a submodule,
I will generalize the syntax diagram for module itself.
Previously, a module name was assumed to be a single identifier,
so we used this syntax diagram for module.
To access objects from a submodule,
I can use this generalized syntax for module
as a sequence of identifiers separated by dots.
For example, the standard library contains a module called OS,
which provides access to operating system functions and other objects.
Inside the OS module is a submodule called path that contains a function called isfile.
The isfile function returns true if its string argument is the name of
a file that exists in the folder that Python is run from, and false otherwise.
I can use this generalized syntax for module to access this function.
I will call the isfile function on the string sleep.py,
and the function returns true since the file that my programming is in certainly exists.
I will call the isfile function on the string snuvs.py,
and the function returns false since
there's no file called snuvs.py in my Python program folder.
In this video, I generalize the import statement so it can be used to
resolve name conflicts and to import objects from submodules,
which are modules inside of other modules.