Страхующий код для getattr()
Ревьюрер просит написать страхующий код для getattr(), но я не понимаю как это реализовать. Использовать лучше ValueError или TypeError? AttributeError использовать не рекомендует. И как правильно это вставить в код?
Кратко цель задачи:
В первой строке записано количество команд n — целое число, не превосходящее 5000.
Во второй строке записано число m — максимальный размер дека. Он не превосходит 1000.
В следующих n строках записана одна из команд:
- push_back(value) – добавить элемент в конец дека. Если в деке уже находится максимальное число элементов, вывести «error».
- push_front(value) – добавить элемент в начало дека. Если в деке уже находится максимальное число элементов, вывести «error».
- pop_front() – вывести первый элемент дека и удалить его. Если дек был пуст, то вывести «error».
- pop_back() – вывести последний элемент дека и удалить его. Если дек был пуст, то вывести «error».
На ввод подается:
4
4
push_front 861
push_front -819
pop_back
pop_back
То правильный ответ:
861
-819
Мой код:
class Deque:
def __init__(self, max_size: int):
self._elements = [None] * max_size
self._max_size = max_size
self._head = - 1
self._tail = 0
self._size = 0
def is_empty(self):
return self._size == 0
def push_back(self, value: int):
if self._size == self._max_size:
raise OverflowError
self._elements[self._tail] = value
self._tail = (self._tail + 1) % self._max_size
self._size += 1
def push_front(self, value: int):
if self._size == self._max_size:
raise OverflowError
self._elements[self._head] = value
self._head = (self._head - 1) % self._max_size
self._size += 1
def pop_back(self):
if self.is_empty():
raise IndexError
self._tail = (self._tail - 1) % self._max_size
self._size -= 1
return self._elements[self._tail]
def pop_front(self):
if self.is_empty():
raise IndexError
self._head = (self._head + 1) % self._max_size
self._size -= 1
return self._elements[self._head]
if __name__ == '__main__':
count_command = int(input())
queue = Deque(int(input()))
for _ in range(count_command):
operation, *parameters = input().split()
method = getattr(queue, operation) # здесь вызов
try:
result = method(*parameters)
except (IndexError, OverflowError):
result = 'error'
if result is not None:
print(result)```
Ответы (2 шт):
зачем? у getattr 3 параметра. если третий указать то ты не получишь AttributeError. Укажи туда lambda например, чтобы выполнение зашло в try и там уже либо выкинь исключение которое уже ловишь или действие по умолчанию. не знаю. сам реши.
class Foo: ...
f = Foo()
attr = getattr(f, "unknown", lambda: f)
print(attr())
А логика наверное такая. У тебя operation это пользовательский ввод. А пользователю свойственно ошибаться. Все что тебя просят это не выкидывать некрасивую ошибку AttributeError и стектрейс к ней, а указать, что данной операции нет продолжение невозможно. Ну это я так понял. Как на самом деле я хз
if __name__ == '__main__':
count_command = int(input())
queue = Deque(int(input()))
for _ in range(count_command):
operation, *parameters = input().split()
method = getattr(queue, operation, lambda *a, **k: "Операция не найдена...") # здесь вызов
try:
result = method(*parameters)
except (IndexError, OverflowError):
result = 'error'
if result is not None:
print(result)
Типо такого
У getattr есть параметр default, куда можно поставить значение которое будет возвращаться, если атрибут не найден в объекте. Тогда можно выполнить простую проверку не вызывая/обрабатывая исключения.
Пример:
class SomeClass:
def __init__(self):
self.x = 0
def push(self, val: int):
self.x += val
test_class = SomeClass()
m = 'push'
method = getattr(test_class, m, None)
if method:
method(5)
print(test_class.x) # 5
m = 'poll'
method = getattr(test_class, m, None)
if not method:
print(f'method {m} not found')
В вашем случае, по мимо этого, можно добавить проверку на наличие параметров *parameters если они необходимы, но это уже выходит за рамки вопроса)