A T20 innings in numbers with Python
Every cricket fan quotes strike rates and run rates. Working them out yourself is one of the most enjoyable ways to practise Python.
This program takes a T20 innings (a made-up team), calculates each batter's strike rate, finds the fastest scorer and draws the runs scored in every over. Set the minimum balls faced below and press Run.
Strike rates, the fastest scorer and how the runs came, over by over.
The Python behind it · 21 lines
1min_balls = 10 # only rate batters who faced at least this many balls23# A T20 innings (made-up team): runs and balls for each batter4innings = {"Arjun": (63, 41), "Rishi": (28, 14), "Kunal": (77, 49),5 "Dev": (12, 15), "Yash": (41, 19), "Neel": (22, 9), "Om": (6, 4)}6overs = [8, 12, 6, 14, 9, 7, 11, 5, 10, 16, 9, 8, 13, 6, 12, 18, 9, 15, 20, 13]78print(f"{'Batter':<9}{'R':>4}{'B':>4}{'SR':>8}")9rated = {n: rb for n, rb in innings.items() if rb[1] >= min_balls}10for name, (runs, balls) in sorted(rated.items(), key=lambda kv: -kv[1][0] / kv[1][1]):11 print(f"{name:<9}{runs:>4}{balls:>4}{runs / balls * 100:>8.1f}")1213if rated:14 best = max(rated, key=lambda n: rated[n][0] / rated[n][1])15 print(f"\nFastest scorer: {best} · Total {sum(overs)} in 20 overs")16else:17 print(f"(nobody faced {min_balls} balls, try a smaller number)")18spark = "▁▂▃▄▅▆▇█"19print("Runs per over " + "".join(spark[min(7, r // 3)] for r in overs))20print(" over no. 1 5 10 15 20")21print(f"Death overs (16-20) scored {sum(overs[15:])} — {sum(overs[15:]) / sum(overs):.0%} of the total")
How the code works, step by step
1.The scorecard
A dictionary maps each batter to (runs, balls), and a list holds the runs scored in each of the 20 overs.
3# A T20 innings (made-up team): runs and balls for each batter4innings = {"Arjun": (63, 41), "Rishi": (28, 14), "Kunal": (77, 49),5 "Dev": (12, 15), "Yash": (41, 19), "Neel": (22, 9), "Om": (6, 4)}6overs = [8, 12, 6, 14, 9, 7, 11, 5, 10, 16, 9, 8, 13, 6, 12, 18, 9, 15, 20, 13]2.Strike rates, fastest first
A dictionary comprehension keeps batters who faced enough balls. Strike rate is runs ÷ balls × 100, and sorting by its negative puts the fastest scorer on top.
8print(f"{'Batter':<9}{'R':>4}{'B':>4}{'SR':>8}")9rated = {n: rb for n, rb in innings.items() if rb[1] >= min_balls}10for name, (runs, balls) in sorted(rated.items(), key=lambda kv: -kv[1][0] / kv[1][1]):11 print(f"{name:<9}{runs:>4}{balls:>4}{runs / balls * 100:>8.1f}")3.The fastest scorer
max with a key returns the batter with the best strike rate. The if rated check handles the case where nobody faced that many balls.
13if rated:14 best = max(rated, key=lambda n: rated[n][0] / rated[n][1])15 print(f"\nFastest scorer: {best} · Total {sum(overs)} in 20 overs")16else:17 print(f"(nobody faced {min_balls} balls, try a smaller number)")4.Runs per over and the death overs
Each over's runs pick one of eight block characters to draw a sparkline. Slicing overs[15:] takes overs 16 to 20, and :.0% prints their share as a percentage.
18spark = "▁▂▃▄▅▆▇█"19print("Runs per over " + "".join(spark[min(7, r // 3)] for r in overs))20print(" over no. 1 5 10 15 20")21print(f"Death overs (16-20) scored {sum(overs[15:])} — {sum(overs[15:]) / sum(overs):.0%} of the total")
Make it yours
- Add fours and sixes to each batter and work out the boundary percentage.
- Load a real scorecard from a CSV and compare two innings.
- Calculate the required run rate after every over of a chase.
Questions
- How is strike rate calculated?
- Runs scored divided by balls faced, multiplied by 100. A batter with 41 off 19 balls has a strike rate of about 215.8.
- Is this a real match?
- No. The team and the numbers are made up for practice, so you can change them freely.