Архитектура
Назначение значений по умолчанию при вызове функции является запахом кода.
def a(b=[]):
pass
Это подпись функции, которая бесполезна. Не только из-за проблем, описанных другими ответами. Я не буду вдаваться в подробности.
Эта функция предназначена для двух вещей. Создайте новый список и выполните функцию, скорее всего, в указанном списке.
Функции, которые выполняют две вещи, являются плохими функциями, как мы узнаем из практики чистого кода.
Для решения этой проблемы с полиморфизмом мы бы расширили список python или поместили его в класс, а затем выполнили бы нашу функцию над ним.
Но подождите, вы говорите, мне нравятся мои однострочники.
Ну, угадай, что? Код - это больше, чем просто способ управления поведением оборудования.
Это способ:
общение с другими разработчиками, работающими над тем же кодом.
возможность изменять поведение оборудования при возникновении новых требований.
возможность понять ход выполнения программы после повторного ввода кода через два года для внесения изменений, упомянутых выше.
Не оставляйте бомбы замедленного действия для себя, чтобы забрать их позже.
Чтобы разделить эту функцию на две функции, нам нужен класс
class ListNeedsFives(object):
def __init__(self, b=None):
if b is None:
b = []
self.b = b
def foo():
self.b.append(5)
Выполнено
a = ListNeedsFives()
a.foo()
a.b
И почему это лучше, чем объединять весь вышеприведенный код в одну функцию.
def dontdothis(b=None):
if b is None:
b = []
b.append(5)
return b
Почему бы не сделать это?
Пока ваш проект не провалится, ваш код будет жить. Скорее всего, ваша функция будет делать больше, чем это. Надлежащим способом создания поддерживаемого кода является разделение кода на атомарные части с должным ограничением области действия.
Конструктор класса является общепризнанным компонентом для всех, кто занимался объектно-ориентированным программированием. Размещение логики, которая обрабатывает создание экземпляра списка в конструкторе, делает когнитивную нагрузку понимания того, что делает код меньше.
Метод foo()
не возвращает список, почему бы и нет?
Возвращая автономный список, вы можете предположить, что безопасно делать то, что вам нравится. Но это может быть не так, поскольку он также является общим для объекта a
. Принуждение пользователя ссылаться на него как a.b
напоминает ему о том, где находится список. Любой новый код, который хочет изменить a.b
, естественно будет помещен в класс, которому он принадлежит.
функция подписи def dontdothis(b=None):
не имеет ни одного из этих преимуществ.