相关疑难解决方法(0)

"最小的惊讶"和可变的默认论证

任何修补Python足够长的人都被以下问题咬伤(或撕成碎片):

def foo(a=[]):
    a.append(5)
    return a
Run Code Online (Sandbox Code Playgroud)

Python新手希望这个函数总能返回一个只包含一个元素的列表:[5].结果却非常不同,而且非常惊人(对于新手来说):

>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
Run Code Online (Sandbox Code Playgroud)

我的一位经理曾经第一次遇到这个功能,并称其为该语言的"戏剧性设计缺陷".我回答说这个行为有一个潜在的解释,如果你不理解内部,那确实非常令人费解和意想不到.但是,我无法回答(对自己)以下问题:在函数定义中绑定默认参数的原因是什么,而不是在函数执行时?我怀疑经验丰富的行为有实际用途(谁真的在C中使用静态变量,没有繁殖错误?)

编辑:

巴泽克提出了一个有趣的例子.再加上你的大部分评论和特别是Utaal,我进一步阐述了:

>>> def a():
...     print("a executed")
...     return []
... 
>>>            
>>> def b(x=a()):
...     x.append(5)
...     print(x)
... 
a executed
>>> b()
[5]
>>> b()
[5, 5]
Run Code Online (Sandbox Code Playgroud)

对我而言,似乎设计决策是相对于放置参数范围的位置:在函数内部还是"与它一起"?

在函数内部进行绑定意味着在调用函数时x有效地绑定到指定的默认值,而不是定义,这会产生一个深层次的缺陷:def在某种意义上,该行将是"混合"的(部分绑定)函数对象)将在定义时发生,并在函数调用时发生部分(默认参数的赋值).

实际行为更加一致:执行该行时,该行的所有内容都会得到评估,这意味着在函数定义中.

python language-design least-astonishment default-parameters

2458
推荐指数
31
解决办法
14万
查看次数

(lambda)函数闭包捕获了什么?

最近我开始玩Python,我遇到了一些特殊的闭包方式.请考虑以下代码:

adders=[0,1,2,3]

for i in [0,1,2,3]:
   adders[i]=lambda a: i+a

print adders[1](3)
Run Code Online (Sandbox Code Playgroud)

它构建了一个简单的函数数组,它接受单个输入并返回由数字添加的输入.函数在for循环中构造,迭代器i从中循环03.对于这些数字中的每一个,lambda都会创建一个函数i,该函数捕获并将其添加到函数的输入中.最后一行将第二个lambda函数3作为参数调用.令我惊讶的是输出结果是6.

我期待一个4.我的理由是:在Python中,一切都是一个对象,因此每个变量都是指向它的指针.在创建lambda闭包时i,我希望它存储一个指向当前指向的整数对象的指针i.这意味着当i分配一个新的整数对象时,它不应该影响先前创建的闭包.遗憾的是,adders在调试器中检查数组表明它确实存在.所有的lambda功能指的最后一个值i,3,这将导致adders[1](3)返回6.

这让我想知道以下内容:

  • 闭包捕获的内容是什么?
  • 什么是最优雅的方式来说服lambda函数以更改其值i时不会受到影响的方式捕获当前i值?

python lambda closures

237
推荐指数
5
解决办法
4万
查看次数

Python:为什么functools.partial是必要的?

部分应用很酷.什么功能functools.partial提供你无法通过lambdas?

>>> sum = lambda x, y : x + y
>>> sum(1, 2)
3
>>> incr = lambda y : sum(1, y)
>>> incr(2)
3
>>> def sum2(x, y):
    return x + y

>>> incr2 = functools.partial(sum2, 1)
>>> incr2(4)
5
Run Code Online (Sandbox Code Playgroud)

functools某种程度上更有效,或可读?

python functional-programming partial-application

183
推荐指数
6
解决办法
4万
查看次数

在循环中创建函数

我正在尝试在循环内创建函数并将它们存储在字典中.问题是字典中的所有条目似乎最终都映射到最后创建的函数.代码如下:

functions = []

for i in range(3):
    def f():
        return i

    # alternatively: f = lambda: i

    functions.append(f)
Run Code Online (Sandbox Code Playgroud)

这输出:

print([f() for f in functions])
# expected output: [0, 1, 2]
# actual output:   [2, 2, 2]
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?

python function

79
推荐指数
2
解决办法
3万
查看次数

在Python中使用lambda的tkinter按钮命令

香港专业教育学院尝试寻找解决方案,但找不到一个有效.我有一个2d的tkinter按钮列表,我想在鼠标点击时更改它们的文本.我试过这样做:

def create_board(number):
    print(number)
    for i in range (0,number):
        buttonList.append([])
        for j in range(0,number):
            print(i,j)
            buttonList[i].append(Button(root, text = " ", command = lambda: update_binary_text(i,j)))
            buttonList[i][j].pack()
Run Code Online (Sandbox Code Playgroud)

然后单击它时调用此函数:

def update_binary_text(first,second):
    print(first,second)
    buttonList[first][second]["text"] = "1"
Run Code Online (Sandbox Code Playgroud)

当我点击一个按钮时,它什么都不做,我让程序显示被点击的按钮的索引,并且它们全部显示4,4(这是变量编号= 5时)是否有解决方案?
这是我第一次上课的python尝试.

谢谢

python lambda tkinter list python-3.x

8
推荐指数
1
解决办法
2万
查看次数

Python循环中的Python Generator"链"

我正在尝试为我正在从数据源读取的数据设置"处理管道",并在读取每个项目时应用一系列操作符(使用生成器).

一些演示相同问题的示例代码.

def reader():
    yield 1
    yield 2
    yield 3

def add_1(val):
    return val + 1

def add_5(val):
    return val + 5

def add_10(val):
    return val + 10

operators = [add_1, add_5, add_10]

def main():
    vals = reader()

    for op in operators:
        vals = (op(val) for val in vals)

    return vals

print(list(main()))
Run Code Online (Sandbox Code Playgroud)

期望:[17, 18, 19]
实际:[31, 32, 33]

Python似乎没有op通过for循环保存每次的值,所以它每次都应用第三个函数.有没有办法每次通过for循环将实际的操作符函数"绑定"到生成器表达式?

我可以通过将for循环中的生成器表达式更改为列表解析来解决这个问题,但由于实际数据要大得多,我不希望将它全部存储在内存中的任何一点.

python generator

8
推荐指数
1
解决办法
1211
查看次数

如何在Python中使用for循环生成多个函数?

我试图使用for循环生成具有不同参数i(见下文)的几个函数,但似乎所有这些函数都使用了i的最后一项.有谁能告诉我如何处理这个?

这是一个简化的例子.我实际上需要使用不同的参数生成200多个函数.

funs = ()
for i in range(2):
    f = lambda x: x+i
    funs += (f,)
Run Code Online (Sandbox Code Playgroud)

然后事实证明这两个函数做同样的事情:

funs[0](1)
Run Code Online (Sandbox Code Playgroud)

输出:2

funs[1](1)
Run Code Online (Sandbox Code Playgroud)

输出:2

但我希望第一个函数给出1而不是2的结果.

非常感谢你提前.

python

7
推荐指数
2
解决办法
92
查看次数

无法用lambda包装函数

我想用一个指定的参数包装一个函数,比如functools.partial,但是它没有按预期工作:

source_codes = (0, 1, 2)

def callback(source, *args):
    print 'callback from source: ', source

funcs = []
for source in source_codes:
    funcs.append(lambda *args: callback(source, *args))

for i, func in enumerate(funcs):
    print 'source expected: ', i
    func()
    print
Run Code Online (Sandbox Code Playgroud)

输出:

source expected:  0
callback from source:  2

source expected:  1
callback from source:  2

source expected:  2
callback from source:  2
Run Code Online (Sandbox Code Playgroud)

但是......我想要的是:

source expected:  0
callback from source:  0

source expected:  1
callback from source:  1

source expected:  2 …
Run Code Online (Sandbox Code Playgroud)

python lambda

5
推荐指数
1
解决办法
258
查看次数

for循环中的lambda只占用最后一个值

版问题:

上下文菜单应动态显示过滤器变量,并使用回调内定义的参数执行函数.通用描述显示正确,但函数调用始终使用last set选项执行.

我尝试过的:

#!/usr/bin/env python

import Tkinter as tk
import ttk
from TkTreectrl import MultiListbox

class SomeClass(ttk.Frame):
    def __init__(self, *args, **kwargs):
        ttk.Frame.__init__(self, *args, **kwargs)
        self.pack(expand=True, fill=tk.BOTH)

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

        self.View=MultiListbox(self)

        __columns=("Date","Time","Type","File","Line","-","Function","Message")
        self.View.configure(columns=__columns, expandcolumns=(0,0,0,0,0,0,0,1))

        self.View.bind("", self.cell_context)
        self.View.grid(row=0, column=0, sticky=tk.NW+tk.SE)

        self.__recordset          = []
        self.__recordset_filtered = False

        #Some dummy values
        self.__recordset.append(["Date", "Time", "INFO", "File", "12", "-", "Function", "Message Info"])
        self.__recordset.append(["Date", "Time", "DEBUG", "File", "12", "-", "Function", "Message Info"])
        self.__recordset.append(["Date", "Time", "WARNING", "File", "12", "-", "Function", "Message Info"])

        self.__refresh()

    def cleanView(self):
        self.View.delete(0, …
Run Code Online (Sandbox Code Playgroud)

python lambda contextmenu tkinter

5
推荐指数
2
解决办法
1359
查看次数

Python和Tkinter lambda函数

(正如'家庭作业'标签所示,这是计算机科学项目的一部分.)

我正在写一个危险的!使用tkinter在Python中进行模拟,我在按钮中使用lambda函数时遇到了很大的问题.假设root = Tk()并且categories是一个列表.

# Variable to keep the buttons
root._buttons = {}

# Display headers on top of page
for i in range(5):
    # Get category name for display in main window
    name = categories[i]
    b = Label(root, text=fill(name.upper(), 10), width=18, height=3,\
        bg="darkblue", fg="white", font=("Helvetica bold", "", 11))
    b.grid(row=0, column=i)

    # Create list of buttons in that variable (root._buttons)
    btnlist = [None]*5

    # Display individual questions
    for j in range(5):

        # …
Run Code Online (Sandbox Code Playgroud)

python lambda tkinter

4
推荐指数
1
解决办法
1815
查看次数

带有 Lambda 值的字典更新所有条目

我在 Python 2.7 中。我有两个类和一个命名元组。一个类包含一个字典作为实例属性和一个分配给该字典的函数。(这是情况的一个非常简化的版本)。namedtuple 很简单。另一个类是test_dict通过add_to_test_dict函数调用向其中添加条目的类。

然后我实例化 DictManipulator 并调用test函数:

from collections import namedtuple


class DictHolder(object):
    def __init__(self):
        self.test_dict = {}
    def add_to_test_dict(self, key, val):
        self.test_dict[key] = val

TestTuple = namedtuple('TestTuple', 'name data')

class DictManipulator(object):
    def test(self):
        named_tuple_list = [TestTuple(name='key1', data=1), TestTuple(name='key2', data=1000)]
        self.my_dh = DictHolder()
        for item in named_tuple_list:
            self.my_dh.add_to_test_dict(item.name, lambda: item.data)

my_dm = DictManipulator()
my_dm.test()
print('key1 value: ', my_dm.my_dh.test_dict['key1']())
print('key2 value: ', my_dm.my_dh.test_dict['key2']())
# ('key1 value: ', 1000)
# ('key2 value: ', 1000)
Run Code Online (Sandbox Code Playgroud)

为什么两个键在那里返回相同的值?我已经进行了足够的实验,可以说原始的 …

python lambda namedtuple python-2.7

3
推荐指数
1
解决办法
288
查看次数

PyQt/PySide中连接点击信号时lambda和partial的区别

当将一组按钮中的多个单击信号连接到带有参数的单个槽函数时,我遇到了信号槽问题。

lambda可以functools.partial按如下方式使用:

user = "user"
button.clicked.connect(lambda: calluser(name))

from functools import partial
user = "user"
button.clicked.connect(partial(calluser, name))
Run Code Online (Sandbox Code Playgroud)

虽然在某些情况下,它们的表现有所不同。以下代码显示了一个示例,该示例期望在单击每个按钮时打印每个按钮的文本。但使用该方法时输出始终是“按钮3” lambda。该partial方法符合我们的预期。

我怎样才能找到他们的差异?

from PyQt5 import QtWidgets

class Program(QtWidgets.QWidget):
    def __init__(self):
        super(Program, self).__init__()
        self.button_1 = QtWidgets.QPushButton('button 1', self)
        self.button_2 = QtWidgets.QPushButton('button 2', self)
        self.button_3 = QtWidgets.QPushButton('button 3', self)
        from functools import partial
        for n in range(3):
            bh = eval("self.button_{}".format(n+1)) 
            # lambda method : always print `button 3`
            # bh.clicked.connect(lambda: self.printtext(n+1))
            bh.clicked.connect(partial(self.printtext, n+1))
        
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.button_1)
        layout.addWidget(self.button_2)
        layout.addWidget(self.button_3) …
Run Code Online (Sandbox Code Playgroud)

python lambda partial signals-slots pyqt5

3
推荐指数
1
解决办法
2076
查看次数