Создать новый список и добавить туда элементы, которые подходят под предикат. Типичный map/filter/reduce
def filter_by(self, data: list, param: dict) -> list:
result = []
for el in data:
matches = True
for name, val in param.items():
if el[name] != val:
matches = False
break
if matches:
result.append(el)
return result
Или однострочником
def filter_by(self, data: list, param: dict) -> list:
return [el for el in data if all(el[name] == val for name, val in param.items())]
rule of dumb: если метод/функция меняет свой аргумент, она не должна его возвращать (обычно это значит, что она вообще ничего не должна возвращать), имя метода/функции при этом должно явно говорить, что аргумент меняется (populate, remove_smth, drop_smth). Если метод/функция возвращает что-то, она не должна менять аргументы.
Но нужно понимать, что сложность создания нового списка — O(n) [при условии, что param достаточно мал и не растёт с увеличением data], а сложность выкидывания элементов по индексу — O(n**2) [потому что сложность операции .pop(idx) — O(n), в цикле по data — ещё O(n), итого O(n**2)]