Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
223: The fractions Module
Imagine you're following a recipe that calls for exactly 1/3 of a cup of flour. If you try to measure that using a digital scale that only displays decimals, you're going to see 0.33, or maybe 0.333. No matter how many 3s the screen shows, you're never actually at 1/3; you're just getting closer and closer. In the culinary world, we solve this by using a physical 1/3 cup scoop. The scoop doesn't care about decimals; it just holds the exact ratio required.
In Python, float types are like that digital scale. They're great for most things, but they struggle with certain fractions because they represent numbers in binary. The fractions module is your "measuring scoop." Instead of approximating a value as a decimal, it stores the numerator and denominator as integers, keeping the value perfectly precise.
Why floats let us down
I'll show you something that drives a lot of beginners crazy. Try running 0.1 + 0.2 == 0.3 in your interpreter. You'd expect True, right? But Python will tell you False. If you print the result of 0.1 + 0.2, you'll see something like 0.30000000000000004.
This isn't a bug in Python; it's just how floating-point math works across almost all programming languages. For a video game, that tiny error doesn't matter. But if you're writing software for a bank or a scientific lab, those "crumbs" of precision can add up to a disaster.
Working with the Fraction object
To fix this, we use the Fraction class. You can initialize it by passing the numerator and denominator, or even a string if you want to keep it readable.
from fractions import Fraction
# The direct way: numerator, denominator
half = Fraction(1, 2)
# The string way: cleaner and prevents float conversion issues
third = Fraction('1/3')
print(third) # Output: 1/3
A quick tip: I highly recommend using the string format Fraction('1/3'). If you pass a float like Fraction(0.33), Python will try to create a fraction that represents that exact, slightly-off float, and you'll end up with a massive, ugly fraction like 33/100 or worse.
Automatic simplification and math
One of the best parts about this module is that it handles the "math homework" for you. It automatically reduces fractions to their simplest form. If you create a fraction of Fraction(2, 4), Python immediately stores it as 1/2.
You can also perform standard arithmetic with them, and the result remains a Fraction object, preserving that precision throughout the entire chain of calculations.
from fractions import Fraction
# Let's do some precise math
a = Fraction('1/3')
b = Fraction('1/6')
result = a + b
print(result) # Output: 1/2 (It added 1/3 + 1/6 and simplified 3/6 to 1/2)
# You can even mix them with integers
final_value = result * 10
print(final_value) # Output: 5
Converting back to decimals
Eventually, you'll probably need to show the result to a user who doesn't want to see "1/2" and just wants "0.5". You can do this easily using the float() constructor or the .limit_denominator() method if you're dealing with a complex fraction that you want to round to the nearest "sensible" fraction.
from fractions import Fraction
precise_val = Fraction('1/7')
decimal_val = float(precise_val)
print(decimal_val) # Output: 0.14285714285714285
📋 Practical Task
Exercise: The Precise Pizza Share Calculator
You are building a tool for a party planner to divide a pizza exactly among friends. Because some people are very picky about their slices, you cannot use floats.
Your Task:
- Create a program that takes a total number of pizzas (as an integer) and the number of people sharing them (as an integer).
- Calculate exactly how much of a single pizza each person gets using the
fractions.Fractionmodule. - If you have 3 pizzas and 4 people, the result should be
3/4. - If you have 2 pizzas and 6 people, the result should be simplified to
1/3. - Print the result in a friendly message:
"Each person gets [fraction] of a pizza."
There are no comments for now.