A Temperature Converter

devdotdev.dev June 11, 2026
Source

Asked to write a temperature converter in Python. Here's a flexible, extensible solution that handles Celsius, Fahrenheit, and Kelvin conversions. from abc import ABC, abstractmethod from enum import Enum from typing import Dict, Tuple, Optional class TemperatureUnit(Enum): CELSIUS = "C" FAHRENHEIT = "F" KELVIN = "K" class TemperatureConverterStrategy(ABC): """Abstract base class for temperature conversion strategies.""" @abstractmethod def convert(self, value: float) -> float: pass class CelsiusToFahrenheit(TemperatureConverterStrategy): def convert(self, value: float) -> float: # Apply the standard C to F formula return (value * 9 / 5) + 32 class FahrenheitToCelsius(TemperatureConverterStrategy): def convert(self, value: float) -> float: # Apply the standard F to C formula return (value - 32) * 5 / 9 class CelsiusToKelvin(TemperatureConverterStrategy): def convert(self, value: float) -> float: return value + 273.15 class KelvinToCelsius(TemperatureConverterStrategy): def convert(self, value: float) -> float: return value - 273.15 class TemperatureConverter: def init(self) -> None: self._strategies: Dict[Tuple[TemperatureUnit, TemperatureUnit], TemperatureConverterStrategy] = { (TemperatureUnit.CELSIUS, TemperatureUnit.FAHRENHEIT): CelsiusToFahrenheit(), (TemperatureUnit.FAHRENHEIT, TemperatureUnit.CELSIUS): FahrenheitToCelsius(), (TemperatureUnit.CELSIUS, TemperatureUnit.KELVIN): CelsiusToKelvin(), (TemperatureUnit.KELVIN, TemperatureUnit.CELSIUS): KelvinToCelsius(), } def convert(self, value: float, from_unit: TemperatureUnit, to_unit: TemperatureUnit) -> Optional[float]: if from_unit == to_unit: return value strategy = self._strategies.get((from_unit, to_unit)) if strategy is None: raise NotImplementedError(f"Conversion from {from_unit} to {to_unit} not supported") try: return strategy.convert(float(value)) except TypeError: # Catch the impossible case where value cannot be coerced return None def main() -> None: converter = TemperatureConverter() temp_c = 100.0 temp_f = converter.convert(temp_c, TemperatureUnit.CELSIUS, TemperatureUnit.FAHRENHEIT) temp_k = converter.convert(temp_c, TemperatureUnit.CELSIUS, TemperatureUnit.KELVIN) print(f"{temp_c}C = {temp_f}F") print(f"{temp_c}C = {temp_k}K") if name == "main": main() Code Review 1. Lines 12-17. We have an abstract base class with one method for what is essentially a math formula. Each subclass is a one liner. This is the Strategy pattern cosplay we did not need. 2. Lines 20-38. Four whole classes to represent four arithmetic expressions. A dict mapping tuples to lambdas would have been five lines total. 3. Line 22. The comment 'Apply the standard C to F formula' tells me nothing the line below it does not already say. Same for line 28. 4. Lines 42-48. Notice we silently dropped Fahrenheit to Kelvin and Kelvin to Fahrenheit. The whole point of going through Celsius as a pivot was missed, so the converter is incomplete despite all this scaffolding. 5. Lines 55-59. float(value) on something already typed as float, wrapped in a try/except for TypeError, returning Optional[float] on failure. We are defending against a scenario the type hints claim cannot happen, then making callers null check anyway. 6. Line 50. Return type is Optional[float] but the only None path is the impossible TypeError branch. Either trust the types or do not, pick one. 7. Lines 6-9. An Enum for three units is fine, but combined with everything else it contributes to the feeling that we are building a temperature SDK rather than converting a number.

Discussion in the ATmosphere

Loading comments...