Skip to main content

Modules, imports & the standard library

Level 2: Level 2: Idiomsmedium11 minmodulesimportsstandard-librarycollections

Organise code into modules and reach for Python's batteries-included stdlib.

Why code lives in modules

A 2000-line file is where bugs hide. Real projects split logic across many .py files so each one has a single job, and any file that has been imported once is cached in sys.modules so the second import is nearly free. Just as important: Python ships a huge standard library, so before you write a character counter or a GCD loop by hand, check whether someone already wrote, tested, and optimized it in C for you. Interviewers notice when you reach for collections instead of reinventing it.

A module is just a .py file

Every .py file is a module, and import runs it once and binds its names so you can use them:

import math                     # names live under math.*
math.gcd(12, 8)                 # 4

from math import sqrt           # pull one name into your file
sqrt(9)                         # 3.0

from collections import Counter # a name from the stdlib collections module
Table
Every form binds exactly what the highlighted column says and nothing more. That is why the star import is discouraged: you cannot tell by reading the line which names it just claimed, so a later stdlib addition can quietly shadow a variable of yours.
Import formWhat lands in your namespaceHow you call itTrade-off
import maththe name mathmath.sqrt(9)clear origin, slightly longer to type
from math import sqrtthe name sqrtsqrt(9)short, but the reader cannot see where it came from
import numpy as npthe name npnp.array(...)a community alias; only use well-known ones
from math import *every public name in mathsqrt(9)avoid: it can silently shadow your own names
Every form binds exactly what the highlighted column says and nothing more. That is why the star import is discouraged: you cannot tell by reading the line which names it just claimed, so a later stdlib addition can quietly shadow a variable of yours.

import math keeps names namespaced (math.gcd), which is safest. from math import sqrt copies just sqrt into your file, which is shorter but risks a name clash. Avoid from math import *: it dumps every name in and makes it impossible to tell where a function came from.

Batteries included: Counter and math

Counter is a dict subclass that tallies how often each item appears. The demo below builds one from a string:

from collections import Counter

tally = Counter("aabbbc")
print(tally)                  # Counter({'b': 3, 'a': 2, 'c': 1})
print(tally.most_common(1))   # [('b', 3)]

most_common(k) returns the top k items as (item, count) pairs, already sorted from most to least frequent. That is exactly what the Apply exercise needs: Counter(text).most_common(1)[0][0] is the single most frequent character. For the Practice exercise, math.gcd(a, b) returns the greatest common divisor with no loop of your own: math.gcd(12, 8) is 4.

Check yourself
Your file's only import line is import math. Further down you call gcd(12, 8). What happens?

Pitfall: do not name your file after a stdlib module

If you save your own file as collections.py, your file shadows the real one, and import collections imports your file. You get a confusing ImportError or AttributeError on names that clearly exist. The fix: never name a script after a stdlib module you import, and delete any stray .pyc files or __pycache__ folders left behind. A related trap is mixing import styles: after import math alone, writing gcd(12, 8) raises NameError, because the name lives at math.gcd, not in your file.

Check yourself
What does Counter('abcabx').most_common(1) return? Both a and b appear twice.

Interview nuance: most_common is deterministic even on ties. When two items share the same count, they come back in the order first encountered while building the Counter (guaranteed since Python 3.7). So Counter("abcabx").most_common(1) returns [('a', 2)], not [('b', 2)], because a was seen first. If an interviewer asks "what if two characters tie for most frequent?", the honest answer is that your code returns the first one to reach that count, and if the spec needs a different tiebreak (say, alphabetical) you must sort explicitly rather than trust most_common.

Worked example (Python)
from collections import Counter

tally = Counter("aabbbc")
print(tally)                  # Counter({'b': 3, 'a': 2, 'c': 1})
print(tally.most_common(1))   # [('b', 3)]

Apply

Your turn

The task this lesson builds to.

Implement most_common_char(text): return the character that appears most often in text.

Use collections.Counter. For "aabbbc" return "b".

3 hints and 3 automated checks are waiting in the workspace.

Practice

Make it stick

A second problem on the same idea, so it survives past today.

Implement gcd_of(a, b): return the greatest common divisor of a and b.

Use math.gcd from the standard library. gcd_of(12, 8) is 4.

2 hints and 4 automated checks are waiting in the workspace.