任何修补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
最近我开始玩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从中循环0到3.对于这些数字中的每一个,lambda都会创建一个函数i,该函数捕获并将其添加到函数的输入中.最后一行将第二个lambda函数3作为参数调用.令我惊讶的是输出结果是6.
我期待一个4.我的理由是:在Python中,一切都是一个对象,因此每个变量都是指向它的指针.在创建lambda闭包时i,我希望它存储一个指向当前指向的整数对象的指针i.这意味着当i分配一个新的整数对象时,它不应该影响先前创建的闭包.遗憾的是,adders在调试器中检查数组表明它确实存在.所有的lambda功能指的最后一个值i,3,这将导致adders[1](3)返回6.
这让我想知道以下内容:
lambda函数以更改其值i时不会受到影响的方式捕获当前i值?部分应用很酷.什么功能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某种程度上更有效,或可读?
我正在尝试在循环内创建函数并将它们存储在字典中.问题是字典中的所有条目似乎最终都映射到最后创建的函数.代码如下:
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)
知道为什么吗?
香港专业教育学院尝试寻找解决方案,但找不到一个有效.我有一个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尝试.
谢谢
我正在尝试为我正在从数据源读取的数据设置"处理管道",并在读取每个项目时应用一系列操作符(使用生成器).
一些演示相同问题的示例代码.
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循环中的生成器表达式更改为列表解析来解决这个问题,但由于实际数据要大得多,我不希望将它全部存储在内存中的任何一点.
我试图使用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的结果.
非常感谢你提前.
我想用一个指定的参数包装一个函数,比如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) 版问题:
上下文菜单应动态显示过滤器变量,并使用回调内定义的参数执行函数.通用描述显示正确,但函数调用始终使用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) (正如'家庭作业'标签所示,这是计算机科学大项目的一部分.)
我正在写一个危险的!使用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 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)
为什么两个键在那里返回相同的值?我已经进行了足够的实验,可以说原始的 …
当将一组按钮中的多个单击信号连接到带有参数的单个槽函数时,我遇到了信号槽问题。
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 ×12
lambda ×7
tkinter ×3
closures ×1
contextmenu ×1
function ×1
generator ×1
list ×1
namedtuple ×1
partial ×1
pyqt5 ×1
python-2.7 ×1
python-3.x ×1