Добавил:
YagamiRam
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:1 семестр / Лабораторные работы / Лабораторная работа №5 / sensors
.py# Импорт библиотеки
import random
# --- Базовый класс Sensor ---
class Sensor:
def __init__(self, id, calibration_factor, unit):
"""
Инициализирует базовый датчик.
:param id: Уникальный идентификатор датчика
:param calibration_factor: Фактор калибровки (инкапсулирован)
:param unit: Единица измерения
"""
self._id = id
# Используем сеттер для проверки и установки фактора калибровки
self.calibration_factor = calibration_factor
self._unit = unit
@property
def id(self):
"""Свойство для доступа к идентификатору датчика."""
return self._id
@property
def calibration_factor(self):
"""Свойство для доступа к фактору калибровки."""
return self._calibration_factor
@calibration_factor.setter
def calibration_factor(self, value):
"""
Сеттер для фактора калибровки.
Проверяет, что значение — число.
"""
if not isinstance(value, (int, float)):
raise ValueError("Коэффициент калибровки должен быть числом!")
self._calibration_factor = value
@property
def unit(self):
"""Свойство для доступа к единице измерения."""
return self._unit
def read_data(self):
"""
Симуляция чтения данных с датчика.
Возвращает случайное значение, умноженное на фактор калибровки.
"""
raw_value = random.uniform(0, 100)
calibrated_value = raw_value * self.calibration_factor
return calibrated_value
def __str__(self):
"""Строковое представление датчика для пользователя."""
return f"Sensor(id={self.id}, unit={self.unit})"
def __repr__(self):
"""Строковое представление датчика для разработчика."""
return f"Sensor(id={self.id!r}, calibration_factor={self.calibration_factor!r}, unit={self.unit!r})"
# --- Класс AdvancedSensor, наследующий от Sensor ---
class AdvancedSensor(Sensor):
def __init__(self, id, calibration_factor, unit, precision, last_calibration_date):
"""
Инициализирует продвинутый датчик.
:param precision: Точность датчика (влияет на шум)
:param last_calibration_date: Дата последней калибровки
"""
# Вызов конструктора родительского класса
super().__init__(id, calibration_factor, unit)
self._precision = precision
self._last_calibration_date = last_calibration_date
@property
def precision(self):
"""Свойство для доступа к точности датчика."""
return self._precision
@precision.setter
def precision(self, value):
"""
Сеттер для точности датчика.
Проверяет, что значение — положительное число.
"""
if not isinstance(value, (int, float)) or value <= 0:
raise ValueError("Точность должна быть положительным числом!")
self._precision = value
@property
def last_calibration_date(self):
"""Свойство для доступа к дате последней калибровки."""
return self._last_calibration_date
def read_data(self):
"""
Переопределение метода read_data.
Добавляет шум, зависящий от точности.
"""
raw_value = super().read_data() # Получаем откалиброванное значение из родителя
# Генерируем шум, обратно пропорциональный точности (чем выше точность, тем меньше шум)
noise = random.uniform(-1, 1) / self.precision
noisy_value = raw_value + noise
return noisy_value
def __str__(self):
"""Строковое представление продвинутого датчика."""
return f"AdvancedSensor(id={self.id}, unit={self.unit}, precision={self.precision})"
def __repr__(self):
"""Строковое представление продвинутого датчика для разработчика."""
return f"AdvancedSensor(id={self.id!r}, calibration_factor={self.calibration_factor!r}, unit={self.unit!r}, precision={self.precision!r}, last_calibration_date={self.last_calibration_date!r})"
# --- Класс Experiment ---
class Experiment:
def __init__(self, name, start_date):
"""
Инициализирует эксперимент.
:param name: Название эксперимента
:param start_date: Дата начала эксперимента
"""
self._name = name
self._start_date = start_date
# Композиция: эксперимент содержит список датчиков
self._sensor_list = []
@property
def name(self):
"""Свойство для доступа к названию эксперимента."""
return self._name
@property
def sensor_list(self):
"""Свойство для доступа к списку датчиков."""
return self._sensor_list
def add_sensor(self, sensor):
"""
Добавляет датчик в эксперимент.
:param sensor: Объект Sensor или его наследника
"""
if not isinstance(sensor, Sensor):
raise TypeError("Можно калибровать только объекты типа Sensor или его подклассы!")
self._sensor_list.append(sensor)
def run(self, iterations=5):
"""
Запускает эксперимент: собирает данные со всех датчиков.
:param iterations: Количество итераций сбора данных
:return: Список словарей с результатами
"""
results = []
for i in range(iterations):
iteration_data = {"iteration": i + 1}
for sensor in self._sensor_list:
# Используем полиморфизм: вызываем read_data, который может быть переопределён
value = sensor.read_data()
iteration_data[f"sensor_{sensor.id}"] = value
results.append(iteration_data)
return results
def get_average_readings(self):
"""
Вычисляет среднее значение для каждого датчика за всё время эксперимента.
:return: Словарь {sensor_id: average_value}
"""
if not self._sensor_list:
return {}
averages = {}
# Запускаем эксперимент, чтобы получить данные
data = self.run(iterations=10) # Собираем 10 итераций для усреднения
for sensor in self._sensor_list:
key = f"sensor_{sensor.id}"
values = [d[key] for d in data]
avg = sum(values) / len(values)
averages[sensor.id] = avg
return averages
def __str__(self):
"""Строковое представление эксперимента."""
return f"Experiment(name={self.name}, sensors={len(self._sensor_list)})"
def __repr__(self):
"""Строковое представление эксперимента для разработчика."""
return f"Experiment(name={self.name!r}, start_date={self._start_date!r}, sensor_list={self._sensor_list!r})"
# --- Класс Calibrator (доп. задание) ---
class Calibrator:
"""
Класс для калибровки датчиков.
"""
@staticmethod
def calibrate(sensor, new_factor):
"""
Изменяет фактор калибровки датчика.
:param sensor: Объект Sensor или его наследника
:param new_factor: Новый фактор калибровки
"""
if not isinstance(sensor, Sensor):
raise TypeError("Можно калибровать только объекты типа Sensor или его подклассы!")
sensor.calibration_factor = new_factor
print(f"Датчик {sensor.id} откалиброван с фактором {new_factor}.")
Соседние файлы в папке Лабораторная работа №5
