Python - Speed up an A Star Pathfinding Algorithm
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
A* is fast when its heuristic is good and its implementation is careful, but Python versions slow down quickly if they create too many objects or use inefficient data structures. The biggest gains usually come from a better priority queue, cheaper node bookkeeping, and a heuristic that stays admissible while pruning more of the search space.
Start With heapq
The open set should be a binary heap, not a repeatedly sorted list.
If you sort a Python list or scan for the minimum on every iteration, you are wasting time in the hottest part of the algorithm.
Use Lightweight Node State
Avoid wrapping every node in a custom class unless you truly need it. Tuples, dictionaries, and arrays are usually faster and simpler in Python.
This structure avoids heavy per-node objects and keeps the hot loop compact.
Pick The Right Heuristic
For a four-direction grid, Manhattan distance is usually the right heuristic. For eight-direction movement with diagonal cost, a diagonal-aware heuristic is better.
A weak heuristic turns A* into something closer to Dijkstra's algorithm. A strong admissible heuristic reduces how many nodes you expand.
Reduce Repeated Work
Hot-path performance also improves when you:
- keep blocked cells in a fast structure
- avoid recomputing neighbors in expensive ways
- skip stale heap entries with a
closedset or best-score check - store dimensions and local references outside inner loops
In Python, small constant-factor reductions matter because the loop runs many times.
Consider The Map Representation
If the grid is large, representation matters. A nested Python list works, but for very big maps, compact numeric arrays such as NumPy arrays can reduce memory pressure and improve locality for some workloads.
Even without NumPy, using integers and tuples is usually better than storing rich node objects with many attributes.
Algorithmic Improvements
Past a certain point, micro-optimizations will not save a poor search strategy. Depending on the map, larger gains may come from:
- bidirectional search
- hierarchical pathfinding
- jump point search on uniform-cost grids
- precomputed navigation graphs instead of raw cell search
Those are bigger design changes, but they often beat tiny Python-level tuning.
Common Pitfalls
A common mistake is using a list for the open set and calling min() or sorting on every loop. That becomes expensive fast.
Another mistake is choosing a heuristic that overestimates the remaining cost. That can break optimality.
It is also easy to spend time on Python object design while ignoring search-space size. The fastest code is often the code that avoids exploring unnecessary nodes in the first place.
Summary
- Use
heapqfor the open set. - Keep node bookkeeping lightweight with tuples, dicts, and sets.
- Match the heuristic to the movement rules of the grid.
- Avoid repeated work inside the hot loop.
- If simple tuning is not enough, consider algorithmic upgrades such as bidirectional search or jump point search.
Related reading
- Python - Tree traversal question
- Python and OpenCV - Improving my lane detection algorithm
- Python Brute Force algorithm
- Python CMA-ES Algorithm to solve user-defined function and constraints
- Python Continuing to next iteration in outer loop
- Python Dictionary Comprehension
- Python - TypeError Object of type 'int64' is not JSON serializable
- python - TypeError unorderable types str float

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.