The idea behind the module.attribute naming convention is two-fold. Primarily it is a way to allow massive parallel development without having to worry about name clashes. Imagine what a pain it would be to write software if you had to verify that every function name and variable name you use in your program is never been used in any other Python module. With module.attribute I can write a function that has the same name as an attribute in numpy or matplotlib or sqlite3 or tkinter and still use those packages.
The second, and less important reason for module.attribute is consistent with the way attributes are specified for other Python container types who's attributes are specified by name: classes and named tuples for example. If you think of the module as a container and the function or class as an attribute, container.attribute is a very pleasing and logical way to specify an attribute outside the local namespace. I wish they had done the same thing with "global" so I could do global.x = 5 instead of:
global x
x = 5
The module.attribute naming convention is more natural when modules contain more than one attribute. For example, the random module has random.choice, random.sample, random.uniform as well as random.random. The time module has time.asctime, time.strftime and time.sleep as well as time.time.