Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Importing and creating modules
Sundeep
Sundeep

Posted on • Originally published atlearnbyexample.github.io

     

Importing and creating modules

The previous chapters focused on data types, functions (both built-in and user defined) and control structures. This chapter will show how to use built-in as well as user defined modules. Quoting fromdocs.python: Modules:

A module is a file containing Python definitions and statements. The file name is the module name with the suffix.py appended.

Random numbers

Say you want to generate a random number from a given range for a guessing game. You could write your own random number generator. Or, you could save development/testing time, and make use of therandom built-in module.

Here's an example guessing game.

# rand_number.pyimportrandom# gives back an integer between 0 and 10 (inclusive)rand_int=random.randrange(11)print('I have thought of a number between 0 and 10.')print('Can you guess it within 4 attempts?\n')for_inrange(4):guess=int(input('Enter your guess: '))ifguess==rand_int:print('Wow, you guessed it right!')breakelifguess>rand_int:print('Oops, your guess is too high.')else:print('Oops, your guess is too low.')else:print('\nOh no! You are out of chances. Better luck next time.')
Enter fullscreen modeExit fullscreen mode

import random will load this built-in module for use in this script, you'll see more details aboutimport later in this chapter. Therandrange() method follows the samestart/stop/step logic as therange() function and returns a random integer from the given range. Thefor loop is used here to get the user input for a maximum of4 attempts. The loop body doesn't need to know the current iteration count. In such cases,_ is used to indicate a throwaway variable name.

As mentioned in the previous chapter,else clause is supported by loops too. It is used to execute code if the loop is completed normally. If the user correctly guesses the random number,break will be executed, which isnot a normal loop completion. In that case, theelse clause willnot be executed.

A sample run with correct guess is shown below.

$python3.9 rand_number.pyI have thought of a number between 0 and 10Can you guess it within 4 attempts?Enter your guess: 5Oops, your guess is too low.Enter your guess: 8Oops, your guess is too high.Enter your guess: 6Wow, you guessed it right!
Enter fullscreen modeExit fullscreen mode

Here's a failed guess.

$python3.9 rand_number.pyI have thought of a number between 0 and 10.Can you guess it within 4 attempts?Enter your guess: 1Oops, your guess is too low.Enter your guess: 2Oops, your guess is too low.Enter your guess: 3Oops, your guess is too low.Enter your guess: 4Oops, your guess is too low.Oh no! You are out of chances. Better luck next time.
Enter fullscreen modeExit fullscreen mode

Importing your own module

All the programs presented so far can be used as a module as it is without making further changes. However, that'll lead to some unwanted behavior. This section will discuss these issues and the next section will show how to resolve them.

# num_funcs.pydefsqr(n):returnn*ndeffact(n):total=1foriinrange(2,n+1):total*=ireturntotalnum=5print(f'square of{num} is{sqr(num)}')print(f'factorial of{num} is{fact(num)}')
Enter fullscreen modeExit fullscreen mode

The above program defines two functions, one variable and calls theprint() function twice. After you've written this program, open an interactive shell from the same directory. Then, load the module usingimport num_funcs wherenum_funcs is the name of the program without the.py extension.

>>>importnum_funcssquareof5is25factorialof5is120
Enter fullscreen modeExit fullscreen mode

So what happened here? Not only did thesqr andfact functions get imported, the code outside of these functions got executed as well. That isn't what you'd expect on loading a module. Next section will show how to prevent this behavior. For now, continue the REPL session.

>>>num_funcs.sqr(12)144>>>num_funcs.fact(0)1>>>num_funcs.num5
Enter fullscreen modeExit fullscreen mode

As an exercise,

  • add docstrings for the above program and check the output ofhelp() function usingnum_funcs,num_funcs.fact, etc as arguments.
  • check what would be the output ofnum_funcs.fact() for negative integers and floating-point numbers. Then import themath built-in module and repeat the process withmath.factorial(). Go through theException handling chapter and modify the above program to gracefully handle negative integers and floating-point numbers.

How does Python know where a module is located? Quoting fromdocs.python: The Module Search Path:

When a module namedspam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file namedspam.py in a list of directories given by the variablesys.path.sys.path is initialized from these locations:

• The directory containing the input script (or the current directory when no file is specified).

• PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).

• The installation-dependent default.

__name__ special variable

The special variable__name__ will be assigned thestring value'__main__' only for the program file that is executed. The files that are imported inside another program will see their own filename (without the extension) as the value for the__name__ variable. This behavior allows you to code a program that can act as a module as well as execute extra code if and only if it is run as the main program.

Here's an example to illustrate this behavior.

# num_funcs_module.pydefsqr(n):returnn*ndeffact(n):total=1foriinrange(2,n+1):total*=ireturntotalif__name__=='__main__':num=5print(f'square of{num} is{sqr(num)}')print(f'factorial of{num} is{fact(num)}')
Enter fullscreen modeExit fullscreen mode

When you run the above program as a standalone application, theif condition will get evaluated toTrue.

$python3.9 num_funcs_module.pysquare of 5 is 25factorial of 5 is 120
Enter fullscreen modeExit fullscreen mode

On importing, the aboveif condition will evaluate toFalse asnum_funcs_module.py is no longer the main program. In the below example, the REPL session is the main program.

>>>__name__'__main__'>>>importnum_funcs_module>>>num_funcs_module.sqr(12)144>>>num_funcs_module.fact(0)1# 'num' variable inside the 'if' block is no longer accessible>>>num_funcs_module.numTraceback(mostrecentcalllast):File"<stdin>",line1,in<module>AttributeError:module'num_funcs_module'hasnoattribute'num'
Enter fullscreen modeExit fullscreen mode

In the above example, there are three statements that'll be executed if the program is run as the main program. It is common to put such statements under amain() user defined function and then call it inside theif block.

There are many such special variables and methods withdoubleunderscores around their names. They are also called asdunder variables and methods. Seestackoverflow: __name__ special variable for a detailed discussion and strange use cases.

Different ways of importing

When you useimport <module> statement, you'll have to prefix the module name whenever you need to use its features. If this becomes cumbersome, you can use alternate ways of importing.

First up, removing the prefix altogether as shown below. This will load all names from the module except those beginning with a_ character. Use this feature only if needed, one of the other alternatives might suit better.

>>>frommathimport*>>>sin(radians(90))1.0>>>pi3.141592653589793
Enter fullscreen modeExit fullscreen mode

Instead of using*, a comma separated list of names is usually enough.

>>>fromrandomimportrandrange>>>randrange(3,10,2)9>>>frommathimportcos,pi>>>cos(pi)-1.0
Enter fullscreen modeExit fullscreen mode

You can also alias the name being imported using theas keyword. You can specify multiple aliases with comma separation.

>>>importrandomasrd>>>rd.randrange(4)1>>>frommathimportfactorialasfact>>>fact(10)3628800
Enter fullscreen modeExit fullscreen mode

__pycache__ directory

If you notice the__pycache__ directory after you import your own module,don't panic. Quoting fromdocs.python: Compiled Python files:

To speed up loading modules, Python caches the compiled version of each module in the__pycache__ directory under the namemodule.version.pyc, where the version encodes the format of the compiled file; it generally contains the Python version number. For example, in CPython release 3.3 the compiled version of spam.py would be cached as__pycache__/spam.cpython-33.pyc. This naming convention allows compiled modules from different releases and different versions of Python to coexist.

You can usepython3.9 -B if you do not wish the__pycache__ directory to be created.

Explore modules

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Addicted to writing books and teaching. Likes fantasy books, comics and anime
  • Joined

More fromSundeep

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp