Python - передавать только аргументы, если существует переменная
У меня есть следующие переменные, которые пользователь может отправить через форму (они не требуются, но могут сделать это, чтобы отфильтровать поиск).
color = request.GET.get ('color')
size = request.GET.get ('size')
Теперь я хочу передать эти переменные функции, но только если они существуют. Если они не существуют, я хочу просто запустить функцию без аргументов.
функция без аргументов:
apicall = search ()
с цветом только это
apicall = search (color)
и с цветом и размером
apicall = search (color, size)
Если аргумент определен, я хочу передать его функции, но если это не так, я не хочу его передавать.
Каков наиболее эффективный способ сделать это? Есть ли у python встроенные методы для этого?
Ответы
Ответ 1
Предполагая, что стандартный вызов get
(например, в словаре), это должно быть легко. Определите свою функцию с помощью None
для параметров по умолчанию для ваших параметров, а затем передайте color
и size
, не утруждая себя проверкой!
def apicall(color=None, size=None):
pass # Do stuff
color = request.GET.get('color')
size = request.GET.get('size')
apicall(color, size)
Таким образом, вы проверяете только аргументы None
в одном месте (внутри вызова функции, где вам все равно нужно проверить, может ли функция вызываться несколькими способами). Все остается красивым и чистым. Конечно, это предполагает (как я сказал вверху), что ваш вызов get
похож на обычный метод словаря Python get
, который возвращает None
, если значение не найдено.
Наконец, я заметил, что ваше имя функции apicall
: есть шанс, что у вас фактически нет доступа к самому коду функции. В этом случае, поскольку вы можете ничего не знать о значениях по умолчанию для сигнатуры функции, а None
может быть неправильным, я, вероятно, просто напишу простую оболочку для проверки аргументов. Затем вы можете вызвать оболочку, как указано выше.
def wrapped_apicall(color=None, size=None):
if color is None and size is None:
return apicall()
# At least one argument is not None, so...
if size is None:
# color is not None
return apicall(color)
if color is None:
# size is not None
return apicall(size)
# Neither argument is None
return apicall(color, size)
ПРИМЕЧАНИЕ.. Эта вторая версия не нужна, если вы не видите код, который вы вызываете, и у вас нет документации! Использование None
в качестве аргумента по умолчанию очень распространено, поэтому есть вероятность, что вы можете просто использовать первый способ. Я бы использовал только метод обертки, если вы не можете изменить вызываемую вами функцию, и вы не знаете, каковы ее аргументы по умолчанию (или его аргументы по умолчанию являются модульными константами или чем-то, но это довольно редко).
Ответ 2
Как бы мне ни нравилось @HenryKeiterрешение, Python предоставляет НАМНОГО более простой способ проверки параметров. На самом деле есть несколько разных решений.
- Например, если
search()
является автономной функцией и вы хотите просмотреть аргументы, вы можете использовать модуль inspect, как показано в этом решении.
Пример кода 1
>>> import inspect
>>> print(inspect.getfullargspec(search))
ArgSpec(args=['size', 'color'], varargs=None, keywords=None, defaults=(None, None))
- Однако, если
search()
является методом класса (мы назовем его Search
), то вы можете просто использовать встроенную функцию vars, чтобы увидеть все методы класса и их параметры:
Пример кода 2
>>> import Search
>>> print(vars(Search))
mappingproxy({'__init__': <function Search.__init__(self, size, color)>,
'search': <function Search.search(self, size, color)})
Единственное предостережение, связанное со вторым методом, заключается в том, что он более полезен в качестве инструмента визуального контроля, чем программного, хотя технически можно сказать if 'size' in vars(Search)['search']: do something
. Это просто не было бы очень надежно. Проще и прочнее сказать if 'size' in inspect.getfullargspec(Search.search).args: do something
или for arg in inspect.getfullargsspec(Search.search).args: do something
Ответ 3
meybe вы можете использовать что-то вроде этого:
try:
apicall = search (color, size)
else:
apicall = search(color)
Ответ 4
В Python 3 вы можете упаковать их в список, отфильтровать его и использовать *
-operator, чтобы распаковать список в качестве аргументов для search
:
color = request.GET.get ('color')
size = request.GET.get ('size')
args = [ arg for arg in [color, size] if arg ]
search(*args)
Обратите внимание, однако, что если color
ложный, а size
верный, вы бы вызывали search
с 1 аргументом, равным значению size
, что, вероятно, было бы неправильно, но в исходном вопросе не упоминается желаемое поведение в этом случае.
(некромант, так как я искал лучшее решение, чем мое, но нашел этот вопрос)
Ответ 5
Когда вы определяете свой метод, если вы задаете аргумент по умолчанию, вы можете указать аргумент или нет.
def search(color=None, size=None):
pass
Затем, когда вы его вызываете, вы можете указать аргумент ключевого слова по своему усмотрению. Оба они были бы действительны:
apicall = search(color=color)
apicall = search(size=size)