Мне просто было интересно, как в Python было бы предпочтительнее сделать группу аргументов функции необязательной, но только как всю группу. Значение: они должны быть либо все даны, либо ни один.
Например, предположим, что я хочу создать функцию print
, которая принимает строку сообщения в качестве первого позиционного аргумента и, необязательно, файлоподобный объект и кодировку в качестве второго и третьего аргументов.
Теперь я хочу, чтобы эта функция печатала на стандартный вывод, если файл не указан, и в файл в противном случае. Хитрость заключается в следующем: я хочу, чтобы эта функция всегда требовала указания кодировки всякий раз, когда используется файл. И вызов этой функции с кодировкой, но никаким файлом тоже нельзя запрещать.
В Java я мог бы перегрузить функцию и дать реализации для обоих допустимых вариантов:
public void print(string message);
public void print(string message, File f, string encoding);
Это позволяет мне вызывать эту функцию именно двумя способами, которые я хочу, с одним или всеми тремя аргументами.
В Python я могу сделать отдельные аргументы необязательными, указав значение по умолчанию, но я не могу сгруппировать их вместе.
def print(msg, file=None, encoding=None)
Позволяет мне вызвать функцию, предоставив сообщение и ни один, оба или только один из других параметров:
print("test")
print("test", file=someFile)
print("test", encoding="utf-8")
print("test", file=someFile, encoding="utf-8")
Все это допустимые вызовы объявления Python выше, даже несмотря на то, что в моей реализации установка кодировки или файла без другой может не иметь смысла.
Я знаю, что могу просто проверить оба параметра на наличие недопустимого значения по умолчанию и вызвать исключение во время выполнения всякий раз, когда я нахожу, что установлен только один, но я думаю, что это плохо по нескольким причинам:
- Исключение возникает только в том случае, если выполняется недопустимый вызов, поэтому во время тестирования это может не произойти.
- Я не могу сказать, что оба параметра необходимы как пара, просто взглянув на объявление или автоматически сгенерированный краткий справочник, не углубляясь в реализацию.
- Ни один инструмент анализа кода не смог бы предупредить меня о недопустимом вызове.
Итак, есть ли лучший способ синтаксически указать, что несколько необязательных аргументов сгруппированы вместе?
3 ответа
Python не поддерживает методы перегрузки. И нет действительно хорошего способа имитировать перегруженный дизайн. Лучшее, что вы можете сделать, это использовать операторы if с разными параметрами. Как и вы в своем методе.
Я имею в виду, что вы можете заставить один параметр ожидать кортеж в качестве входных данных. Как и idk, 2D-массив может иметь атрибут size
, который требует ввода в форме (x, y). Хотя это не избавит вас от необходимости во время выполнения проверять, имеют ли смысл предоставленные значения, не так ли?
После прочтения других ответов мне кажется, что наиболее простым и читаемым решением было бы написать функцию со всеми обязательными параметрами, а затем добавить вторую функцию-оболочку, которая имеет сокращенный набор параметров, передает эти аргументы в исходная функция включена, а также дает значения по умолчанию для других параметров:
def print(msg, file, encoding):
# no default values here, so no parameter is optional
pass
def printout(msg):
# forward the argument and provide default values for the others
print(msg, sys.stdout, "")
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.
if file is not None and encoding is None: raise TypeError("print() missing 1 argument: 'encoding'
?