Здесь есть две отдельные проблемы.
Первая относится к PyCharm и использует модуль ввода .Он генерирует файлы Pyi с заглушками, определяющими API различных сторонних библиотек (таких как PyQt), чтобы обеспечить автоматическое заполнение и тому подобное.Кроме того, он поддерживает определяемые пользователем подсказки типов и файлы pyi, которые описаны здесь: Подсказка типов в PyCharm .Однако, поскольку я не являюсь пользователем PyCharm, я не могу дать практического совета о том, как именно вы должны определить свои собственные заглушки перегрузки, чтобы они дополняли существующие заглушки PyQt.Я полагаю, что это должно быть возможно.
Второй вопрос касается именно того, как реализовать перегрузки функций для существующих API-интерфейсов PyQt.Короткий ответ на это таков: вы не можете: Python просто не поддерживает перегрузки так же, как C ++.Это потому, что Python динамически типизирован, поэтому такой тип перегрузки не имеет смысла.Однако можно обойти это различными способами, чтобы обеспечить эквивалентное поведение.
Для вашего конкретного случая простейшее решение требует небольшого компромисса.Ваш вопрос гласит: «Обратите внимание, что мой новый аргумент QVariant находится на втором месте, и я хочу, чтобы он был позиционным, а не ключевым словом».Если вы готовы отказаться от этого требования, это облегчает задачу , потому что вы можете определить свой подкласс следующим образом:
class MyListWidgetItem(QListWidgetItem):
def __init__(self, *args, value=None, **kwargs):
super().__init__(*args, **kwargs)
или вот так:
class MyListWidgetItem(QListWidgetItem):
def __init__(self, *args, **kwargs):
value = kwargs.pop('value', None)
super().__init__(*args, **kwargs)
Эти подклассы будут поддерживать все существующие перегрузки PyQt без необходимости точно знать, как они определены, поскольку вы просто передаете аргументы базовой реализации.Пользователь должен предоставить правильные аргументы, но поскольку базовый класс предоставляется PyQt, он автоматически вызовет TypeError
, если заданы неправильные аргументы.Все это помогает сделать реализацию очень простой, но она делает ставку на правильное документирование ваших API, учитывая, что сама сигнатура функции практически не дает подсказки о том, какими должны быть правильные аргументы.Однако, если вы также можете найти способ использовать поддержку хинтинга типов в PyCharm, как предложено выше, это должно приблизить вас к очень простому, работающему решению.
Но что, если вы не готовы идти на компромисс??Непосредственную проблему, которая возникает при этом, можно увидеть, если рассмотреть эту подпись:
QListWidgetItem(parent: QListWidget = None, type: int = QListWidgetItem.Type)
Это позволяет создать элемент с без аргументов .Но это немедленно перекрывает любую новую перегрузку, которая определяет обязательные аргументы, так как Python вызовет TypeError
, если они отсутствуют при вызове конструктора во время выполнения.Единственный способ обойти это - использовать подпись *args, **kwargs
, а затем явно проверить количество и тип всех аргументов в теле __init__
.По сути, это то, что functools.singledispatch и сторонние пакеты, такие как multipledispatch , делают только через декораторы.Это на самом деле не обходит вышеупомянутую проблему - оно просто перемещает ее в другое место и избавляет вас от необходимости поддерживать весь груз сложного кода котельной плиты.
Я не собираюсь отправлять сообщенияпримеры в стиле здесь: во-первых, потому что я понятия не имею, как они будут работать в PyCharm (или даже PyQt, в этом отношении), и во-вторых, потому что они уже были рассмотрены в более общих SO-вопросах, таких как этот: Python functionперегрузки .Мой совет - начать с гораздо более простой реализации, приведенной выше, а затем подумать об экспериментировании с другими подходами, если вы обнаружите, что действительно нужно добавить перегрузки с аргументами без ключевых слов.
Oneпоследний подход к рассмотрению - это то, что можно назвать стандартной перегрузкой кухонной раковины.При таком подходе вы просто забудете о сигнатурах существующих API-интерфейсов и определите свой подкласс примерно так:
class MyListWidgetItem(QListWidgetItem):
def __init__(self, text='', value=None, parent=None, icon=None,
item=None, type=QListWidgetItem.Type):
if item is not None:
super().__init__(item)
elif icon is not None:
super().__init__(icon, text, parent, type)
else:
super().__init__(text, parent, type)
Или, если вас не волнует type
и конструктор копирования:
class MyListWidgetItem(QListWidgetItem):
def __init__(self, text='', value=None, parent=None, icon=None):
if icon is not None:
super().__init__(icon, text, parent)
else:
super().__init__(text, parent)
Подавляющее большинство кода Python / PyQt, вероятно, использует некоторые варианты такого подхода.Таким образом, практичность превосходит чистоту , я думаю ...