Validieren von Funktionsargumenten
Bei der Erstellung von Funktionen in Python ist es wichtig, zu überprüfen, ob die an Ihre Funktionen übergebenen Argumente gültig sind, bevor Sie mit der Hauptlogik der Funktion fortfahren. In diesem Schritt lernen wir verschiedene Techniken zur Validierung von Funktionsargumenten kennen.
Erstellen einer neuen Python-Datei
Erstellen wir eine neue Datei, um mit Validierungskonzepten zu arbeiten:
- Klicken Sie im WebIDE auf das Menü "Datei" ("File")
- Wählen Sie "Neue Datei" ("New File")
- Geben Sie
validate_args.py als Dateinamen ein
- Klicken Sie auf "OK"
Grundlegende Validierung mit Bedingungen
Der einfachste Weg, Argumente zu validieren, ist die Verwendung von bedingten Anweisungen. Beginnen wir mit einigen grundlegenden Validierungen:
def calculate_rectangle_area(length, width):
"""Calculate the area of a rectangle, validating inputs."""
## Validate that inputs are numbers
if not isinstance(length, (int, float)):
raise TypeError("Length must be a number")
if not isinstance(width, (int, float)):
raise TypeError("Width must be a number")
## Validate that inputs are positive
if length <= 0:
raise ValueError("Length must be positive")
if width <= 0:
raise ValueError("Width must be positive")
## Calculate the area
return length * width
## Test with valid inputs
try:
area = calculate_rectangle_area(5, 3)
print(f"Area of rectangle: {area}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
## Test with invalid types
try:
area = calculate_rectangle_area("5", 3)
print(f"Area of rectangle: {area}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
## Test with invalid values
try:
area = calculate_rectangle_area(5, -3)
print(f"Area of rectangle: {area}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
Speichern und ausführen:
python3 validate_args.py
Ausgabe:
Area of rectangle: 15
Error: Length must be a number
Error: Width must be positive
Diese Funktion validiert sowohl die Typen als auch die Werte ihrer Argumente, bevor Berechnungen durchgeführt werden. Wenn ungültige Argumente erkannt werden, werden entsprechende Fehlermeldungen ausgelöst.
Verwenden von Assertions zur Validierung
Eine andere Möglichkeit, Argumente zu validieren, ist die Verwendung von Assertions. Assertions sind Anweisungen, die einen AssertionError auslösen, wenn eine Bedingung nicht erfüllt ist:
def calculate_discount(price, discount_percent):
"""Calculate the discounted price."""
## Assert that inputs are valid
assert isinstance(price, (int, float)), "Price must be a number"
assert isinstance(discount_percent, (int, float)), "Discount must be a number"
assert price >= 0, "Price cannot be negative"
assert 0 <= discount_percent <= 100, "Discount must be between 0 and 100"
## Calculate the discount
discount_amount = price * (discount_percent / 100)
return price - discount_amount
## Test with valid inputs
try:
discounted_price = calculate_discount(100, 20)
print(f"Discounted price: ${discounted_price}")
except AssertionError as e:
print(f"Error: {e}")
## Test with invalid discount percentage
try:
discounted_price = calculate_discount(100, 120)
print(f"Discounted price: ${discounted_price}")
except AssertionError as e:
print(f"Error: {e}")
Speichern und ausführen:
python3 validate_args.py
Ausgabe:
Discounted price: $80.0
Error: Discount must be between 0 and 100
Assertions sind nützlich für die Entwicklung und das Debugging, können aber im Produktionscode deaktiviert werden, daher sind sie nicht immer die beste Wahl für die Validierung in realen Anwendungen.
Verwenden von Typ-Hinweisen zur Dokumentation
Python 3.5+ unterstützt Typ-Hinweise (type hints), die helfen können, die erwarteten Typen von Funktionsargumenten und Rückgabewerten zu dokumentieren. Während Typ-Hinweise selbst keine Laufzeitvalidierung durchführen, bieten sie nützliche Dokumentation und können von externen Tools wie mypy überprüft werden:
def calculate_average(numbers: list[float]) -> float:
"""Calculate the average of a list of numbers."""
if not numbers:
raise ValueError("Cannot calculate average of empty list")
if not all(isinstance(n, (int, float)) for n in numbers):
raise TypeError("All elements must be numbers")
return sum(numbers) / len(numbers)
## Test with valid input
try:
avg = calculate_average([1, 2, 3, 4, 5])
print(f"Average: {avg}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
## Test with empty list
try:
avg = calculate_average([])
print(f"Average: {avg}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
## Test with non-numeric elements
try:
avg = calculate_average([1, 2, "3", 4, 5])
print(f"Average: {avg}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
Speichern und ausführen:
python3 validate_args.py
Ausgabe:
Average: 3.0
Error: Cannot calculate average of empty list
Error: All elements must be numbers
Beachten Sie, dass die Typ-Hinweise (list[float] und -> float) selbst keine Validierung durchführen – wir müssen immer noch unseren eigenen Validierungscode schreiben. Sie dienen als Dokumentation und können von externen Tools überprüft werden.
Erstellen einer robusten Funktion mit Validierung
Wenden wir nun all diese Techniken an, um eine robuste Funktion zu erstellen, die die Gesamtkosten von Artikeln mit einem Rabatt berechnet:
def calculate_total_cost(items=None, tax_rate=0, discount=0):
"""
Calculate the total cost of items with tax and discount.
Args:
items: List of (item_name, price) tuples
tax_rate: Tax rate percentage (0-100)
discount: Discount percentage (0-100)
Returns:
A dictionary with the total, subtotal, tax amount, and discount amount
"""
## Validate items
if items is None:
items = []
if not isinstance(items, list):
raise TypeError("Items must be a list")
## Validate each item in the list
for i, item in enumerate(items):
if not isinstance(item, tuple) or len(item) != 2:
raise ValueError(f"Item {i} must be a tuple of (name, price)")
name, price = item
if not isinstance(name, str):
raise TypeError(f"Name of item {i} must be a string")
if not isinstance(price, (int, float)):
raise TypeError(f"Price of item {i} must be a number")
if price < 0:
raise ValueError(f"Price of item {i} cannot be negative")
## Validate tax_rate and discount
if not isinstance(tax_rate, (int, float)):
raise TypeError("Tax rate must be a number")
if not isinstance(discount, (int, float)):
raise TypeError("Discount must be a number")
if not (0 <= tax_rate <= 100):
raise ValueError("Tax rate must be between 0 and 100")
if not (0 <= discount <= 100):
raise ValueError("Discount must be between 0 and 100")
## Calculate the total
subtotal = sum(price for _, price in items)
discount_amount = subtotal * (discount / 100)
tax_amount = (subtotal - discount_amount) * (tax_rate / 100)
total = subtotal - discount_amount + tax_amount
return {
"subtotal": subtotal,
"discount_amount": discount_amount,
"tax_amount": tax_amount,
"total": total
}
## Test with valid inputs
shopping_cart = [
("Laptop", 1000),
("Mouse", 25),
("Keyboard", 45)
]
try:
result = calculate_total_cost(shopping_cart, tax_rate=8.5, discount=10)
print("Shopping Cart Total:")
for key, value in result.items():
print(f" {key.replace('_', ' ').title()}: ${value:.2f}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
## Test with invalid item
try:
invalid_cart = [
("Laptop", 1000),
("Mouse", "twenty-five"), ## Invalid price
("Keyboard", 45)
]
result = calculate_total_cost(invalid_cart)
print(result)
except (TypeError, ValueError) as e:
print(f"Error with invalid item: {e}")
Speichern und ausführen:
python3 validate_args.py
Ausgabe:
Shopping Cart Total:
Subtotal: $1070.00
Discount Amount: $107.00
Tax Amount: $81.86
Total: $1044.86
Error with invalid item: Price of item 1 must be a number
Diese Funktion demonstriert eine robuste Validierung durch:
- Überprüfen der Typen aller Eingaben
- Validieren des Bereichs numerischer Werte
- Bereitstellen detaillierter Fehlermeldungen
- Festlegen sinnvoller Standardwerte für optionale Parameter
- Verwenden von Docstrings zur Dokumentation der erwarteten Eingaben und Rückgabewerte
Durch die Implementierung einer gründlichen Validierung in Ihren Funktionen können Sie Fehler verhindern, den Benutzern ein besseres Feedback geben und Ihren Code robuster und wartungsfreundlicher machen.