Конечно, большинство языков программирования делают порядок параметров частью контракта вызова функции, но это не обязательно . С чего бы это? Итак, я понимаю вопрос, отличается ли Python от других языков программирования в этом отношении. Помимо других хороших ответов для Python 2, обратите внимание на следующее:
__named_only_start = object()
def info(param1,param2,param3,_p=__named_only_start,spacing=10,collapse=1):
if _p is not __named_only_start:
raise TypeError("info() takes at most 3 positional arguments")
return str(param1+param2+param3) +"-"+ str(spacing) +"-"+ str(collapse)
Единственный способ, которым вызывающий абонент сможет предоставить аргументы spacing
и collapse
позиционно (без исключения):
info(arg1, arg2, arg3, module.__named_only_start, 11, 2)
Соглашение об отказе от использования закрытых элементов, принадлежащих другим модулям, уже является очень простым в Python. Как и в случае с самим Python, это соглашение для параметров будет применяться только наполовину.
В противном случае вызовы должны были бы иметь форму:
info(arg1, arg2, arg3, spacing=11, collapse=2)
Вызов
info(arg1, arg2, arg3, 11, 2)
присвоит параметру значение 11 _p
и исключение, вызванное первой инструкцией функции.
Характеристики:
- Параметры перед
_p=__named_only_start
допускаются позиционно (или по имени).
- Параметры после
_p=__named_only_start
должны быть предоставлены только по имени (если не __named_only_start
получены и не использованы сведения о специальном контрольном объекте ).
Плюсы:
- Параметры являются точными по количеству и значению (конечно, позднее, если также будут выбраны хорошие имена).
- Если дозорный указан в качестве первого параметра, тогда все аргументы необходимо указать по имени.
- При вызове функции можно переключиться в позиционный режим, используя объект-дозорный
__named_only_start
в соответствующей позиции.
- Можно ожидать лучшую производительность, чем другие альтернативы.
Минусы:
Проверка происходит во время выполнения, а не во время компиляции.
- Использование дополнительного параметра (но не аргумента) и дополнительной проверки. Небольшое снижение производительности по сравнению с обычными функциями.
- Функциональность - это взлом без прямой поддержки языком (см. Примечание ниже).
- При вызове функции можно переключиться в позиционный режим, используя контрольный объект
__named_only_start
в правильном положении. Да, это тоже можно рассматривать как профи.
Имейте в виду, что этот ответ действителен только для Python 2. Python 3 реализует аналогичный, но очень элегантный механизм с поддержкой языка, описанный в других ответах.
Я обнаружил, что, когда я открываю свой разум и думаю об этом, ни один вопрос или чужое решение не кажется глупым, глупым или просто глупым. Напротив: я обычно многому учусь.
_named_only_start
, становится невозможным ссылаться на нее из внешнего модуля, что устраняет плюсы и минусы. (одиночные начальные подчеркивания в области видимости модуля являются частными, IIRC)__named_only_start
и anamed_only_start
(без начального подчеркивания), второй, чтобы указать, что именованный режим «рекомендуется», но не до уровня «активно продвигаемого» (поскольку один является публичным, а другого нет). Что касается «приватности»_names
начала с подчеркивания, она не очень сильно обеспечивается языком: ее можно легко обойти, используя определенные (не *) импорта или уточненные имена. Вот почему в некоторых документах Python предпочитают использовать термин «закрытый» вместо «частный».Вы можете сделать это способом, который работает как в Python 2, так и в Python 3 , сделав «фиктивный» аргумент первого ключевого слова со значением по умолчанию, которое не будет встречаться «естественно». Этому аргументу ключевого слова может предшествовать один или несколько аргументов без значения:
Это позволит:
но нет:
Если вы измените функцию на:
тогда все аргументы должны иметь ключевые слова и
info(odbchelper)
больше не будут работать.Это позволит вам разместить дополнительные аргументы ключевого слова в любом месте после
_kw
, не заставляя вас помещать их после последней записи. Это часто имеет смысл, например, логическая группировка или упорядочение ключевых слов в алфавитном порядке может помочь в поддержке и развитии.Таким образом, нет необходимости возвращаться к использованию
def(**kwargs)
и потере информации подписи в интеллектуальном редакторе. Ваш социальный контракт заключается в предоставлении определенной информации, заставляя (некоторые из них) требовать ключевые слова, порядок, в котором они представлены, стал неактуальным.источник
Обновить:
Я понял, что использование
**kwargs
не решит проблему. Если ваши программисты изменяют аргументы функции по своему усмотрению, можно, например, изменить функцию на это:и старый код снова сломается (потому что теперь каждый вызов функции должен включать первый аргумент).
Все сводится к тому, что говорит Брайан.
В общем, при изменении функций новые аргументы всегда должны идти до конца. В противном случае это нарушит код. Должно быть очевидно.
Если кто-то изменит функцию так, что код сломается, это изменение должно быть отклонено.
(Как говорит Брайан, это похоже на контракт)
Посмотрев на сигнатуру функции (т.е.
def info(object, spacing=10, collapse=1)
), можно сразу увидеть, что каждый аргумент, не имеющий значения по умолчанию, является обязательным.То , для чего нужен аргумент, должно быть указано в строке документации.
Старый ответ (сохранен для полноты) :
Вероятно, это не лучшее решение:Вы можете определять функции таким образом:
kwargs
- словарь, содержащий любой аргумент ключевого слова. Вы можете проверить, присутствует ли обязательный аргумент, а если нет, вызвать исключение.Обратной стороной является то, что уже может быть не так очевидно, какие аргументы возможны, но с правильной строкой документации все должно быть в порядке.
источник
Аргументы только для ключевых слов python3 (
*
) можно смоделировать в python2.x с помощью**kwargs
Рассмотрим следующий код python3:
и его поведение:
Это может быть смоделировано с помощью следующего, заметьте , я взял на себя смелость перехода
TypeError
кKeyError
в случае «требуется названный аргумент», это не было бы слишком много работы , чтобы сделать это же типа исключений , а такжеИ поведение:
Рецепт одинаково работает и в python3.x, но его следует избегать, если вы используете только python3.x
источник
kwargs.pop('foo')
идиома Python 2? Мне нужно обновить свой стиль кодирования. Я все еще использовал этот подход в Python 3 🤔Вы можете декларировать свои функции
**args
только как принимающие . Это потребует аргументов ключевого слова, но вам потребуется дополнительная работа, чтобы убедиться, что передаются только действительные имена.источник
foo(**kwargs)
. Что я на это скажу?foo(killme=True, when="rightnowplease")
dict
.Как говорят другие ответы, изменение сигнатур функций - плохая идея. Либо добавьте новые параметры в конец, либо исправьте каждого вызывающего, если аргументы вставлены.
Если вы все еще хотите это сделать, используйте декоратор функций и функцию inspect.getargspec . Это будет использоваться примерно так:
Реализация
require_named_args
оставлена в качестве упражнения для читателя.Я бы не стал заморачиваться. Каждый раз при вызове функции он будет медленным, и вы получите лучшие результаты, если будете писать код более тщательно.
источник
Вы можете использовать
**
оператор:таким образом люди вынуждены использовать именованные параметры.
источник
в python, если используется * args, это означает, что вы можете передать n-число аргументов для этого параметра - это будет список внутри функции для доступа
и если использовать ** kw, что означает его аргументы ключевого слова, которые могут быть доступны как dict - вы можете передать n-число аргументов kw, и если вы хотите ограничить, что пользователь должен ввести последовательность и аргументы по порядку, тогда не используйте * и ** - (его питонический способ предоставить общие решения для больших архитектур ...)
если вы хотите ограничить свою функцию значениями по умолчанию, вы можете проверить внутри него
источник
Я не понимаю, зачем программист вообще добавляет параметр между двумя другими.
Если вы хотите, чтобы параметры функции использовались с именами (например
info(spacing=15, object=odbchelper)
), тогда не имеет значения, в каком порядке они определены, поэтому вы также можете поместить новые параметры в конец.Если вы действительно хотите, чтобы порядок имел значение, не ожидайте, что что-то сработает, если вы его измените!
источник