【问题标题】:How do I convert apply(map, args) to map(function, iterable) in this case?在这种情况下,如何将 apply(map, args) 转换为 map(function, iterable)?
【发布时间】:2014-05-19 02:07:25
【问题描述】:

我下载了一个 MultiListBox 小部件,以及我成功应用的排序扩展。但是,这个小部件在 python 3 中从未对我有用。库是 Tkinter (py2) 和 tkinter (py3)。

所以,我离工作越来越近了,但有一部分我不太明白如何过去。 apply() 函数已被弃用,而且似乎在 py3 中也没有。随它吧。

这是我不明白的:

我们有 apply(function, args [, keywords])map(function, iterable...)

apply() 函数的调用方式如下:

return apply(map, [None] + result)(结果是字符串元组的列表)

documentation 建议我采用将apply(function, *args, **keywords) 转换为function(*args, **keywords) 的方法。这一切都很好,但我不知道要传递什么作为新函数。

return map(what_am_i, result)

这里有一些相关的代码sn-ps。希望这一切都清楚,但随时要求更多。谢谢。

我添加了更多代码来为这里发生的事情提供上下文。也许这会产生一些见解,使这段代码更beautiful

在此示例中,result 包含长度为 3(列)的 list1000-tuples(行)。 1000-tuples 中的每个元素都是一个 string,其中包含 SubjectSenderDate

我现在更新了完整的 _sort() 函数。

现在,我已经更新了另一个重构 apply() 的实例。我不妨把这件事弄清楚到这个问题中,以便其他人都可以享受。

from tkinter import *

class MultiListbox(Frame):
    def __init__(self, master, rowslist):
        Frame.__init__(self, master)
        self.rowslist = []
        self.colmapping = {}
        self.origData = None
        for (row, colwidth) in rowslist:
            frame = Frame(self);
            b = Button(frame, ...)
            b.bind(...)
            listbox = Listbox(frame, ...)
            self.rowslist.append(listbox)
            listbox.bind(...)
            ...
        ...
    ...
    def _scroll(self, *args):
        for row in self.rowslist:
            row.yview(None, args)
            # apply(row.yview, args)
    ...
    def get(self, first, last=None):
        result = []
        for row in self.rowslist:
            result.append(row.get(first,last))
        if last:
            return map(None, result)
            #return apply(map, [None] + result)
        return result
    ...
    def _sort(self, e):
        # get the listbox to sort by (mapped by the header button)
        b=e.widget
        col, direction = self.colmapping[b]     

        # get the entire table data into mem
        tableData = self.get(0,END)
        if self.origData == None:
            import copy
            self.origData = copy.deepcopy(tableData)

        rowcount = len(tableData)

        #remove old sort indicators if it exists
        for btn in self.colmapping:
            lab = btn.cget('text')
            if lab[0]=='<': btn.config(text=lab[4:])

        btnLabel = b.cget('text')
        #sort data based on direction
        if direction==0:
            tableData = self.origData
        else:
            if direction==1: b.config(text='<+> ' + btnLabel)
            else: b.config(text='<-> ' + btnLabel)
            # sort by col
            tableData.sort(key=lambda x: x[col], reverse=direction<0)

        #clear widget
        self.delete(0,END)

        # refill widget
        for row in range(rowcount):
            self.insert(END, tableData[row])

        # toggle direction flag
        if direction == 1:
            direction = -1
        else:
            direction = direction + 1

        self.colmapping[b] = (col, direction)
        # =:> End of complete _sort(self, e) <:= #
    ...

if __name__ == '__main__':
    tk = Tk()
    Label(tk, text='SortableMultiListbox').pack()
    mlb = MultiListbox(tk, (('Subject', 40), ('Sender', 20), ('Date', 10)))
    for i in range(1000):
        mlb.insert(END, ('Important Message: %d' % i, 'John Doe', '10/10/%04d' % (1900+i)))
    mlb.pack(expand=YES,fill=BOTH)
    tk.mainloop()

【问题讨论】:

    标签: python python-2.7 python-3.x tkinter


    【解决方案1】:
    apply(map, [None] + result)
    

    等价于

    map(*[None] + result)
    

    或者,也许更易读,

    map(None, *result)
    

    请注意,如果您想要转置,最好使用zip(*result)

    >>> # Usually the same behavior:
    ... result = [[1, 2, 3], [4, 5, 6]]
    >>> map(None, *result)
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(*result)
    [(1, 4), (2, 5), (3, 6)]
    >>> # But if result has only one iterable in it:
    ... result = [[1, 2, 3]]
    >>> map(None, *result)
    [1, 2, 3]
    >>> zip(*result)
    [(1,), (2,), (3,)]
    

    【讨论】:

    • 啊哈哈哈..我喜欢它。这就是为什么我不知道要放什么函数:我根本不应该传递任何函数。非常蟒蛇。谢谢。
    • 一个更好的问题可能是你为什么要这样做?
    • @Inversus:注意:如果您想要转置操作,请考虑zip(*result)。它主要做同样的事情,但人们会更容易识别它,并且在 result 只包含一个可迭代的情况下它会做一些更合理的事情。
    • @user2357112 zip() 很有趣,你认为我可以在我的用例中使用它吗?如果 rowslist 变量中只有 1 行,它会崩溃吗?我用新代码和代码正上方的一段文本编辑了我的问题。感谢您的帮助。
    • @Inversus:看起来zip 比较合适。根据您对这段代码的理解程度,它可能值得更改,也可能不值得更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多