import math from decimal import Decimal, InvalidOperation import unicodedata class Worker: SURNAME_SEPARATORS = {"-", "'"} def __init__(self, surname: str, position: str, salary: float): self.surname = None self.position = None self.salary = None self.set_surname(surname) self.set_position(position) self.set_salary(salary) # ----------------------- # проверка фамилии def set_surname(self, surname: str): self.surname = self.validate_surname(surname) @staticmethod def validate_surname(surname: str) -> str: surname = unicodedata.normalize("NFKC", surname.strip()) surname = surname.replace("’", "'").replace("`", "'").replace("−", "-") if len(surname) < 2: raise ValueError("Фамилия слишком короткая") if surname[0] in Worker.SURNAME_SEPARATORS or surname[-1] in Worker.SURNAME_SEPARATORS: raise ValueError("Фамилия не может начинаться или заканчиваться разделителем") previous_is_separator = False for char in surname: if char in Worker.SURNAME_SEPARATORS: if previous_is_separator: raise ValueError("Фамилия содержит подряд идущие разделители") previous_is_separator = True continue if not char.isalpha(): raise ValueError("Фамилия может содержать только буквы, дефис и апостроф") previous_is_separator = False parts: list[str] = [] token = "" for char in surname: if char in Worker.SURNAME_SEPARATORS: parts.append(token) parts.append(char) token = "" else: token += char parts.append(token) normalized_parts = [part[:1].upper() + part[1:].lower() if part not in Worker.SURNAME_SEPARATORS else part for part in parts] return "".join(normalized_parts) # проверка должности def set_position(self, position: str): self.position = self.validate_position(position) @staticmethod def validate_position(position: str) -> str: position = position.strip() if len(position) < 2: raise ValueError("Должность слишком короткая") if not all(x.isalpha() or x.isspace() for x in position): raise ValueError("Должность должна содержать только буквы и пробелы") return position.lower() # проверка оклада def set_salary(self, salary: float): self.salary = self.validate_salary(salary) @staticmethod def validate_salary(salary: float) -> float: if not isinstance(salary, (int, float)): raise ValueError("Оклад должен быть числом") if not math.isfinite(salary): raise ValueError("Оклад не может быть NaN или бесконечностью") salary_decimal = Decimal(str(salary)) if salary_decimal.as_tuple().exponent < -2: raise ValueError("Оклад должен содержать не более 2 знаков после запятой") if salary < 1000: raise ValueError("Оклад слишком маленький (<1000)") if salary > 10_000_000: raise ValueError("Оклад слишком большой (>10_000_000)") return float(salary) # метод №1 — увеличить оклад на 15% def increase_salary(self): self.salary *= 1.15 # метод №2 — если фамилия начинается с "Иван", присвоить должность "инженер" def assign_engineer_if_ivan(self): if self.surname.lower().startswith("иван"): self.position = "инженер" # строка информации об объекте def info(self) -> str: return f"Фамилия: {self.surname}, Должность: {self.position}, Оклад: {self.salary:.2f}" # ----------------------- # функции ввода с проверкой def input_surname() -> str: while True: surname = input("Введите фамилию: ").strip() try: return Worker.validate_surname(surname) except ValueError as e: print("Ошибка:", e) def input_position() -> str: while True: position = input("Введите должность: ").strip() try: return Worker.validate_position(position) except ValueError as e: print("Ошибка:", e) def input_salary() -> float | None: while True: salary_str = input("Введите оклад: ").strip().replace(",", ".") try: salary_decimal = Decimal(salary_str) except InvalidOperation: print("Ошибка: оклад должен быть числом") continue try: return Worker.validate_salary(float(salary_decimal)) except ValueError as e: print("Ошибка:", e) def input_worker() -> Worker: surname = input_surname() position = input_position() salary = input_salary() return Worker(surname, position, salary) # ----------------------- def main(): print("Создание работника с клавиатуры:") worker_from_input = input_worker() # работники-константы worker1 = Worker("Иванов", "менеджер", 50000) worker2 = Worker("Петров", "аналитик", 60000) workers = [worker_from_input, worker1, worker2] print("\nИсходные данные:") for w in workers: print(w.info()) # обработка данных for w in workers: w.increase_salary() w.assign_engineer_if_ivan() print("\nПосле обработки:") for w in workers: print(w.info()) if __name__ == "__main__": main()