Похоже, все ваши виджеты делят обработчик событий. Этот отрывок из Tkinter 8.4 Reference Джона У. Шипмана - NM Tech может помочь.
30.7. Дополнительный аргумент trick
Иногда вам нужно передать другие аргументы обработчику, кроме события.
Вот пример. Предположим, что ваше приложение имеет массив из десяти контрольных кнопок, чьи виджеты хранятся в списке
self.cbList
, индексируются номером контрольной кнопки вrange(10)
.Предположим, что вы хотите написать один обработчик с именем
.__cbHandler
для событийво всех десяти из этих контрольных кнопок. Обработчик может получить фактический виджет
Checkbutton
, который вызвал его, обратившись к атрибуту.widget
объектаEvent
, который передается, но как он узнает, что индекс контрольной кнопки вself.cbList
?Было бы неплохо написать наш обработчик с дополнительным аргументом для номера контрольной кнопки, что-то вроде этого:
def __cbHandler ( self, event, cbNumber ):
Но обработчики событий передаются только одному аргументу - событию. Таким образом, мы не можем использовать вышеприведенную функцию из-за несоответствия количества аргументов.
К счастью, способность Python предоставлять значения по умолчанию для аргументов функции дает нам выход. Посмотрите на этот код:
def __createWidgets ( self ): ? self.cbList = [] # Create the checkbutton list for i in range(10): cb = Checkbutton ( self, ? ) self.cbList.append ( cb ) cb.grid( row=1, column=i ) def handler ( event, self=self, i=i ): # [1] return self.__cbHandler ( event, i ) cb.bind ( "
", handler ) ? def __cbHandler ( self, event, cbNumber ): ?
#
[1] Эти строки определяют новую функциюhandler
, которая ожидает три аргумента. Первый аргумент - это объектEvent
, переданный всем обработчикам событий, а второй и третий аргументы будут установлены в их значения по умолчанию - дополнительные аргументы, которые нам нужно передать.Этот метод может быть расширен для подачи каких-либо дополнительных аргументов обработчикам.
blockquote>Несколько более краткий способ сделать это, поскольку Брайан Оукли делает для второй кнопки в свой ответ , является для определения каждой функции обработчика в строке с помощью лямбда, т. е.
def __createWidgets ( self ): ? self.cbList = [] # Create the checkbutton list for i in range(10): cb = Checkbutton ( self, ? ) self.cbList.append ( cb ) cb.grid( row=1, column=i ) cb.bind ( "
", lambda event, self=self, i=i: self.__cbHandler( event, i ) ) ? def __cbHandler ( self, event, cbNumber ): ?
Поскольку строки являются столбцами в транспонированной матрице; соответствовать вашему примеру; просто
rowMatrix :: [[a]] -> Int -> [a]
rowMatrix xs m = transpose xs !! (m-1)
Я тоже должен был исправить твой тип. Также обратите внимание на проблему off-by-1.
> rowMatrix [[1,2,3,4], [5,6,7,8], [9,10,11,12]] 3
[3,7,11]
it :: [Int]
Мы можем для каждой строки получить k
-й элемент, поэтому мы можем выполнить отображение, например:
romMatrix :: [[a]] -> Int -> [a]
rowMatrix m k = map (!! k) m
Или для типа Matrix
:
Итак, здесь мы создаем список элементов, каждый из которых является k
-ым элементом соответствующего подсписка.
Для каждого подсписка извлеките его n
-й элемент с помощью оператора !!
:
rowMatrix [] _ = []
rowMatrix (row:others) n = (row !! n) : (rowMatrix others n)
Например:
rowMatrix [[1,2,3], [2,3,4]] 2
[3,4]
Вы также можете сделать это немного безумнее , но также более кратким:
rowMatrix :: [[a]] -> Int -> [a]
rowMatrix listOfLists n = listOfLists >>= ((:[]) . (!! n))