Я здесь работаю в Python (который, я думаю, фактически передается по имени), но идея не зависит от языка, пока параметры метода ведут себя аналогично:
Если у меня есть такая функция:
def changefoo(source, destination):
destination["foo"] = source
return destination
и назовите это так,
some_dict = {"foo": "bar"}
some_var = "a"
new_dict = changefoo(some_var, some_dict)
new_dict
будет измененной версией some_dict
, но some_dict
будет также будет изменена.
Предполагая, что изменяемая структура, такая как dict в моем примере, почти всегда будет так же мала, а производительность не является проблемой (в приложении я беру абстрактные объекты и меняю запросы SOAP для различных служб, где запрос SOAP будет займет на порядок больше, чем переформатирование данных для каждой службы), это нормально?
destination
в этих функциях (их несколько, это не просто служебная функция, как в моем примере) всегда будет изменяемым, но мне нравится быть явным: возвращаемое значение функции представляет собой результат детерминированного Вычисление параметров, которые вы передали. Мне не нравится использовать параметры, но в Python нет способа обойти это при передаче изменяемых структур в функцию. Несколько вариантов, которые я обдумал:
Копирование параметров, которые будут изменены, чтобы сохранить оригинал
Я должен был бы скопировать параметры в каждую функцию, где я изменял их, что кажется громоздким и, как будто я просто дублирую. Кроме того, я не думаю, что мне на самом деле понадобится оригинал, просто кажется беспорядочным возвращать ссылку на мутировавший объект, который у меня уже был.
Просто используйте его как параметр входа / выхода
Мне это не нравится, не сразу понятно, что делает функция, и я думаю, что это ужасно.
Создать декоратор, который будет автоматически копировать параметры
похоже на излишество
Так что я делаю хорошо? Мне кажется, что я что-то скрываю, и будущий программист может подумать, что исходный объект сохраняется, основываясь на том, как я вызываю функции (захват его результата, а не полагаться на тот факт, что он мутирует оригинал). Но я также чувствую, что любая из альтернатив будет грязной. Есть ли более предпочтительный способ? Обратите внимание, что на самом деле нельзя добавить метод стиля мутатора в класс, представляющий абстрактные данные, из-за того, как работает программное обеспечение (мне нужно было бы добавить метод для преобразования этой структуры данных в соответствующую структуру SOAP для каждый сервис мы тоже отправляем эти данные - в настоящее время логика перевода находится в отдельном пакете для каждого сервиса)