Можно ли полагаться на автоматическую передачу по ссылке для изменения объектов? - PullRequest
2 голосов
/ 28 мая 2011

Я здесь работаю в 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 для каждый сервис мы тоже отправляем эти данные - в настоящее время логика перевода находится в отдельном пакете для каждого сервиса)

1 Ответ

1 голос
/ 28 мая 2011

Если у вас много подобных функций, я думаю, что вам лучше всего написать небольшой класс, который оборачивает диктовку и изменяет ее на месте:

class DictMunger(object):
    def __init__(self, original_dict):
        self.original_dict = original_dict

    def changefoo(source)
        self.original_dict['foo'] = source

some_dict = {"foo": "bar"}
some_var = "a"

munger = DictMunger(some_dict)
munger.changefoo(some_var)
# ...
new_dict = munger.original_dict

Объекты, модифицирующие себя, обычно ожидаются и читаются хорошо.

...