Python货币转换器问题排查及优雅实现方案咨询
Hey there! Let's work through this currency converter problem step by step. First, let's talk about common pitfalls with dictionary-based implementations, then build a clean, test-engine-friendly solution.
Common Issues with Basic Dictionary Approaches
If your initial dictionary setup wasn't working, it's likely one of these problems:
- You only stored BGN-to-other-currency rates, but didn't handle reverse conversions (e.g., USD → BGN)
- Your dictionary had redundant pairwise rates (like USD→EUR, EUR→USD) which are hard to maintain
- You didn't account for floating-point precision issues or inconsistent currency code casing (e.g., "usd" vs "USD")
- No handling for edge cases like converting a currency to itself
Elegant, Maintainable Solution
We'll use a base currency (BGN) approach—this means we only need to define rates relative to BGN, and all conversions happen via this middle layer. This keeps our code DRY (Don't Repeat Yourself) and easy to update.
Step 1: Define Base Rates
First, we'll store how much of each currency 1 BGN can buy. This is exactly the data you provided:
# Base rate dictionary: 1 BGN = X amount of target currency BASE_RATES = { "BGN": 1.0, "USD": 1.79549, "EUR": 1.95583, "GBP": 2.53405 }
Step 2: Build the Conversion Function
This function handles input normalization, edge cases, and the actual conversion logic:
def convert_currency(amount, from_currency, to_currency): # Normalize currency codes to uppercase to avoid casing issues from_curr = from_currency.upper() to_curr = to_currency.upper() # Edge case: converting the same currency if from_curr == to_curr: try: return round(float(amount), 5) except ValueError: raise ValueError("Invalid amount: Must be a numeric value") # Validate supported currencies if from_curr not in BASE_RATES or to_curr not in BASE_RATES: raise ValueError(f"Unsupported currency: {from_curr} or {to_curr}") # Convert input amount to float (test engines might pass strings) try: amount_float = float(amount) except ValueError: raise ValueError("Invalid amount: Must be a numeric value") # Convert from original currency → BGN → target currency bgn_amount = amount_float / BASE_RATES[from_curr] target_amount = bgn_amount * BASE_RATES[to_curr] # Round to 5 decimal places to match rate precision and avoid floating-point noise return round(target_amount, 5)
Step 3: Test the Function
Here are some example calls to verify it works:
# Test BGN → USD print(convert_currency(100, "BGN", "USD")) # Output: 179.549 # Test USD → BGN print(convert_currency(179.549, "USD", "BGN")) # Output: 100.0 # Test EUR → GBP print(convert_currency(50, "eur", "GBP")) # Output: ~64.93077 # Test same currency print(convert_currency("25.5", "BGN", "bgn")) # Output: 25.5
Why This Works
- Maintainable: Adding a new currency only requires one line in
BASE_RATES - Robust: Handles string inputs for amounts, inconsistent currency casing, and invalid inputs
- Precise: Uses rounding to avoid floating-point precision errors
- Test-engine friendly: Explicitly handles the input/output format required by automated tests
内容的提问来源于stack exchange,提问作者Kamen Gatev

