如何在__init__中调用lambda?

时间:2018-03-13 06:36:30

标签: python python-3.x tkinter lambda

我的大型应用程序涉及的代码很少:

def __init__(self,master):
    self.destroy= lambda num=num : self.destroywidgets(num)

def destroywidgets(self,num):
    if num == 1:
        for widget in self.frame1.winfo_children():
            widget.destroy()
    elif num == 2:
        for widget in self.frame2.winfo_children():
            widget.destroy()
    elif num == 3:
        for widget in self.frame3.winfo_children():
            widget.destroy()

def func1(self):
    self.destroy(1)

这是我的代码的小图片。但是,当我运行此代码时,我收到以下错误:

self.destroy= lambda num=num : self.destroywidgets(num)
NameError: name 'num' is not defined

我真的很困惑,因为这段代码在前一天成功运行。这是今天重启后抛出这样的错误。为什么会出现这种情况? 请注意,我尝试以多种方式改变这个lambda并提到许多SOF答案,仍然无法解决它。

另外,请告诉我是否可以使用partial(functools)来完成。

为了让它更好理解,下面是我制作的小片段:

num = ""

def paint(num):
    if num == 1:
        return "1st paint - green"
    elif num == 2:
        return "1st paint - blue"
    elif num == 3:
        return "1st paint - red"
    else:
        return "no more options"

op = lambda num = num : paint(num)

print(op(2))
print(op(3))
print(op(4))

我得到了完美的输出如下:

1st paint - blue
1st paint - red
no more options

但为什么这不适用于上面的代码呢?

2 个答案:

答案 0 :(得分:1)

在我们解决这个问题之前:

您希望self.destroy成为可以使用num调用的函数,并使用self.destroywidgets调用num。换句话说,你只希望它是self.destroywidgets。所以:

self.destroy = self.destroywidgets

创建一个除了将其参数传递给另一个函数之外什么都不做的lambda只是一种比其他函数做同样事情的更冗长和缓慢的方式。

事实上,这里有一个更简单的解决方案。摆脱__init__,并在课堂上这样做:

destroy = destroywidgets

...因为你所做的一切都是为同样的方法提供另一个名称。

但同时,为什么你现有的代码不起作用?让我们再看一遍:

self.destroy = lambda num=num: self.destroywidgets(num)

有时lambda会让人感到困惑,所以我们将其重写为def

def destroy(num=num):
    self.destroywidgets(num)
self.destroy=destroy

现在,这实际上是合法的语法。这意味着基本相同: *

def destroy(num2=num):
    self.destroywidgets(num2)
self.destroy=destroy

但是您必须有一个名为num的本地或全局变量,其值要用作参数的默认值。你没有这样的变数。而不是因为您的代码的排序方式有任何问题;你真的没有什么可以在这里使用的。而且,幸运的是,您不需要默认值。当您调用该函数时,您传入一个值1

因此,如果您想修复现有代码,可以这样做:

self.destroy = lambda num: self.destroywidgets(num)

但是,再次,你最好只使用self.destroywidget,而不是将它包装在无用的lambda中。

*对于参数使用相同的名称和从中获得默认值的变量,通常会造成混淆,但它是合法的,因为它有一些很好的用途。例如,它是在函数定义时捕获闭包变量当前值的惯用方法,而不是捕获变量本身。

答案 1 :(得分:0)

所以我让它像这样工作:

class Test():
  def __init__(self, master):
    self.destroy= lambda num : self.destroywidgets(num)

  def destroywidgets(self,num):
    if num == 1:
        print 1
    elif num == 2:
        print 2
    elif num == 3:
        print 3

  def func1(self):
    self.destroy(1)

  def func2(self):
    self.destroy(2)

a = Test(1)
a.func1()
# 1
a.func2()
# 2

这里唯一的问题是我没有得到master属性的位置,但是这个解决方案允许创建self.destroy函数并回复输入数