Appearance
Класс как объединение функций
В мире Python функции — это первоклассные объекты: их можно передавать, хранить в переменных, возвращать из других функций. Но когда набор функций логически связан — например, все они оперируют над одними и теми же данными — имеет смысл объединить их в класс. Класс выступает в роли контейнера или неймспейса, в котором функции (ныне — методы) становятся методами одного объекта.
Почему классы вместо набора свободных функций?
- Организация кода: вместо множества отдельных функций мы получаем единый объект с набором методов
obj.method(). - Инкапсуляция: общие детали (например, проверка деления на ноль) можно держать внутри класса, а не дублировать.
- Гибкость: легко расширять, переопределять и комбинировать функции через наследование и декораторы.
Набор функций
Допустим, у нас есть набор независимых функций для арифметики:
python
def addition(a, b):
"""Return sum of a and b."""
return a + b
def subtraction(a, b):
"""Return difference of a and b."""
return a - b
def multiplication(a, b):
"""Return product of a and b."""
return a * b
def division(a, b):
"""Return quotient of a and b, raises if b == 0."""
if b == 0:
raise ValueError("Division by zero")
return a / bОписание кода:
- Каждая функция принимает два аргумента
aиbи возвращает результат соответствующей операции. - Для
divisionдобавлена защита от деления на ноль через выбросValueError. - Такие функции удобно использовать по отдельности, но при увеличении их числа поддерживать код становится сложнее.
Функции в классе
Сгруппируем эти функции внутри класса Operator. Обратите внимание: здесь методы объявлены без параметра self.
python
class Operator:
"""Calculator groups basic arithmetic operations."""
def addition(a, b):
"""Return sum of a and b."""
return a + b
def subtraction(a, b):
"""Return difference of a and b."""
return a - b
def multiplication(a, b):
"""Return product of a and b."""
return a * b
def division(a, b):
"""Return quotient of a and b, raises if b == 0."""
if b == 0:
raise ValueError("Division by zero")
return a / b
operator = Operator # без скобок — ссылка на класс, не экземпляр
print(operator.addition(10, 2)) # 12
print(operator.subtraction(10, 2)) # 8
print(operator.multiplication(10, 2)) # 20
print(operator.division(10, 2)) # 5.0
print(Operator.division(10, 2)) # 5.0 — напрямую по имени классаОсобенности реализации:
- Методы объявлены без
self, поэтому при вызове Python воспринимаетaиbкак первые два аргумента. operator = Operator— здесь мы не создаём экземпляр, а просто присваиваем переменной сам класс.- Вызов
operator.addition(10, 2)эквивалентенOperator.addition(10, 2). - Такая схема может пригодиться для простого объединения функций, но лишена привычной семантики экземпляров.
Функции в классе + self
Чтобы методы работали как истинные методы экземпляра, нужно добавить параметр self и создать объект с помощью скобок:
python
class Operator:
"""Calculator groups basic arithmetic operations."""
def addition(self, a, b):
"""Return sum of a and b."""
return a + b
def subtraction(self, a, b):
"""Return difference of a and b."""
return a - b
def multiplication(self, a, b):
"""Return product of a and b."""
return a * b
def division(self, a, b):
"""Return quotient of a and b, raises if b == 0."""
if b == 0:
raise ValueError("Division by zero")
return a / b
operator = Operator() # скобки — создаём экземпляр класса
print(operator.addition(10, 2)) # 12
print(operator.subtraction(10, 2)) # 8
print(operator.multiplication(10, 2)) # 20
print(operator.division(10, 2)) # 5.0Что изменилось?
- Первый параметр каждого метода —
self— ссылка на текущий экземплярoperator. - Вызов
operator.addition(10, 2)автоматически передаёт внутрьself, аa=10,b=2. - Благодаря
selfв будущем мы сможем хранить состояние внутри объекта.
Статические методы
Когда метод не нуждается ни в атрибутах экземпляра, ни в атрибутах класса, его можно пометить как @staticmethod.
python
class Operator:
"""Calculator groups basic arithmetic operations."""
@staticmethod
def addition(a, b):
"""Return sum of a and b."""
return a + b
@staticmethod
def subtraction(a, b):
"""Return difference of a and b."""
return a - b
@staticmethod
def multiplication(a, b):
"""Return product of a and b."""
return a * b
@staticmethod
def division(a, b):
"""Return quotient of a and b, raises if b == 0."""
if b == 0:
raise ValueError("Division by zero")
return a / b
operator = Operator() # экземпляр, но статические методы можно вызвать любым способом
print(operator.addition(10, 2)) # 12
print(operator.subtraction(10, 2)) # 8
print(operator.multiplication(10, 2)) # 20
print(operator.division(10, 2)) # 5.0
print(Operator.division(10, 2)) # 5.0 — так же срабатывает напрямую по имени классаОсобенности @staticmethod:
- Аннотация отключает передачу
self. - Статические методы в поведении эквивалентны обычным функциям внутри модуля, но логически сгруппированы в классе.
Упражнения
Решения должны содержать полное оформление: явную типологию и описание.
Дополните класс
Operatorметодами:pow(a, b), возведение в степень.mod(a, b), возвращает остаток от деления.floordiv(), возвращает результат целочисленного деления.- и протестируйте его вызовами с экземпляром и через имя класса.
Создайте класс
Converterс@staticmethod, который переводит температуру в разные единицы измерения:fahrenheit_to_celsius(fahrenheit)- °F в °C по формуле:°C = (°F – 32) × 5 ÷ 9.fahrenheit_to_kelvin(fahrenheit)- °F в K по формуле:K = (°F – 32) × 5 ÷ 9 + 273,15.celsius_to_kelvin(celsius)- °C в K по формуле:K = °C + 273.15.celsius_to_fahrenheit(celsius)- °C в °F по формуле:°F = °C × 9 ÷ 5 + 32.kelvin_to_celsius(celsius)- K в °C по формуле:°C = K – 273,15.kelvin_to_farenheit(celsius)- K в °F по формуле:°F = (K – 273,15) × 9 ÷ 5 + 32
Проверьте, что все методы можно вызвать без создания экземпляра класса, например:
pythonprint(Converter.fahrenheit_to_celsius(212)) # 100.0 print(Converter.celsius_to_fahrenheit(0)) # 32.0 print(Converter.kelvin_to_celsius(273.15)) # 0.0 print(Converter.fahrenheit_to_kelvin(-40)) # 233.15 print(Converter.kelvin_to_fahrenheit(373.15)) # 212.0Создайте класс проверки строки как числа со статическими методами проверки:
- целое положительное число,
- целое отрицательное число,
- целое число,
- дробное положительное число,
- дробное отрицательное число,
- дробное число,
- положительное число,
- отрицательное число,
- число,
- число ноль.
Проверьте верность работы методов. Используйте данный класс проверки строки как числа для решения калькулятора полей.
Создайте класс с методами проверки строки для калькулятора котенка:
- проверка название товара: не менее двух символов (минимум одной буквы с одно цифрой или буквы),
- проверка количества товара: целое положительное число, не ноль,
- проверка цены товара: положительное число, не более двух знаков после запятой,
- проверка дня: целое положительное число, не ноль,
- проверка года: целое или половинное число, не ноль. И используйте класс в решении программы калькулятора котенка.