наследование python и функции __init__

Я натолкнулся на код folloqing при поиске некоторых примеров pyQt:

class DisplayPage(QWizardPage): def __init__(self, *args): apply(QWizardPage.__init__, (self, ) + args) 

Что означает * args?
Какова цель использования для этого типа кода?

*args означает, что __init__ принимает любое количество позиционных аргументов, все из которых будут храниться в списке args . Подробнее об этом см. В разделе Что означают * args и ** kwargs?

Этот фрагмент кода использует устаревшую функцию приложения. В настоящее время вы напишете это одним из трех способов:

  QWizardPage.__init__(self, *args) super(DisplayPage, self).__init__(*args) super().__init__(*args) 

Первая строка – это буквальный перевод того, что apply (не используйте его в этом случае, если только QWizardPage не является классом нового стиля ). Второй использует super как определено в PEP 367 . Третий использует super как определено в PEP 3135 (работает только в Python 3.x).

DisplayPage наследуется от QWizardPage . Его конструктор принимает переменное количество аргументов (что и означает * args означает) и передает их всем конструктору своего родителя, QWizardPage

Лучше сказать:

 super(DisplayPage, self).__init__(*args) 

«Списки аргументов переменной длины»: http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/

В основном, это просто сказать, взять все аргументы, которые были переданы методу __init__ DisplayPage, и передать их методу __init__ QWizardPage.

В списке параметров ( определение функции) * args – это способ Python представлять «переменные аргументы» (называемые «varargs» на языках C и C). В списке аргументов ( вызов функции) * args имеет дополнительный смысл … он «применяет» функцию к значению переменной, как если бы они были распакованы и «вставлены» в вызов функции.

Это различие между «параметрами» и «аргументами» является тем, что часто не выяснено. Параметр – это слот, в который помещаются аргументы. Аргументы передаются на вызов функции. Параметры – это имена, по которым аргументы могут быть переданы из области действия функции.

Поэтому, если я определяю функцию:

 def foo(x, *a): print "First arg: ", x print "Other args: ", ' '.join([str(x) for x in a]) 

Я могу назвать это так:

 foo(1, 2, 3, 4) 

… и мой код увидит 1 как «x» (аргумент представляет собой объектную ссылку на целое число 1, привязанную к параметру с именем «x»), а список [2,3,4] – как (аргумент будет быть объектной ссылкой на список трех элементов и привязан к параметру функции с именем «a»).

Если я привяжу следующий кортеж:

 bar = (1, 2, 3, 4) 

… и вызовите foo() таким образом:

 foo(*bar) 

… это будет вызов, который совпадает с моим предыдущим примером. «bar» будет распакован и передан foo() в виде последовательности из 4 аргументов. Эта конкретная функция привязывает 1 к первому параметру и упакует любое количество других аргументов в параметр a. Однако я мог бы назвать еще одну функцию:

 geewhiz(*bar) 

… и было бы передано четыре аргумента так же, как я описал для foo() . (Если geewhiz() был написан, чтобы принимать только 3 аргумента, то Python поднимет TypeError для вызова функции с неправильным количеством аргументов … точно так же, как если бы вы вызвали geewhiz(1,2,3,4) .

В целом поддержка Python для определения функций, принимающих дефолтные аргументы, переменные числа аргументов и аргументы ключевых слов, является более гибкой, чем любой другой язык сценариев, который я когда-либо видел. Однако вся эта сила и гибкость могут быть немного запутанными.

В Python3 они также добавили несколько морщин для назначения пакетов. Назначения упаковки кортежа выглядят так:

 a, b = 1, 2 

… а также часто появляются в коде вроде:

 for key, val in my_dict.items(): ... 

Каждый из элементов возвращается методом .items() как кортеж и упаковывается в ключ, val tuple. (Кортежи в Python не требуют заключений в круглые скобки. Это тег-кортеж).

Теперь в Python3 можно сделать что-то вроде этого:

 a, *b = 1, 2, 3, 4 

… который, как вы могли догадаться, связывает первый элемент с «a», а остальные упаковываются в другой кортеж, привязанный к «b».

Хотя это действительно не связано с * args в списках параметров функций, я упоминаю об этом, потому что они концептуально и синтаксически похожи.