函数可以接受两个输入吗?

5 投票
2 回答
564 浏览
提问于 2025-04-17 14:30

我在上一个类似于Python的课程中学到了以下代码。其实这是一门离散数学课,但老师用Python来演示所有内容。这段代码是用来展示一个多路复用器(multiplexer)以及如何用它构建一个异或门(xor gate)。

def mux41(i0,i1,i2,i3):
    return lambda s1,s0:{(0,0):i0,(0,1):i1,(1,0):i2,(1,1):i3}[(s1,s0)]

def xor2(a,b):
    return mux41(0,1,1,0)(a,b)

xor2这个函数里,我不太明白return mux41(0,1,1,0)(a,b)这段代码的语法。这里的1和0是传给多路复用器的输入,但后面的(a,b)又是干嘛的呢?

2 个回答

5

这段代码对刚学Python的人来说有点复杂,所以你不用觉得自己不明白有什么问题。我觉得它比实际需要的要复杂一些。

def mux41(i0,i1,i2,i3):
    return lambda s1,s0:{(0,0):i0,(0,1):i1,(1,0):i2,(1,1):i3}[(s1,s0)]

这段代码定义了一个函数,它根据两个输入返回一个值。这两个输入是 s1s0。这个函数会创建一个字典,里面预先填充了传给 mux41() 的四个值,然后用 s0s1 来选择这四个值中的一个。

字典是通过键来查找值的。在这里,键是Python的元组:(0, 0)(0, 1)(1, 0)(1, 1)。表达式 (s1, s0) 是从参数 s0s1 创建一个元组。这个元组用作查找字典中值的键。

def xor2(a,b):
    return mux41(0,1,1,0)(a,b)

所以,mux41() 返回一个函数对象,完成我刚才说的事情。xor2() 调用 mux41() 并得到一个函数对象;然后它立即调用这个返回的函数对象,传入 ab 作为参数。最后,它返回结果。

mux41() 创建的函数对象并没有被保存。所以,每次你调用 xor2() 时,都会创建一个新的函数对象,然后这个对象会被垃圾回收。这个函数对象运行时,会构建一个字典对象,这个字典在每次使用后也会被垃圾回收。这可能是我见过的最复杂的XOR函数。

这里有一个重写的版本,可能会让这个过程更清晰。与其使用 lambda 创建一个没有名字的函数对象,不如用 def 创建一个有名字的函数。

def mux41(i0,i1,i2,i3):
    def mux_fn(s1, s0):
        d = {
            (0,0):i0,
            (0,1):i1,
            (1,0):i2,
            (1,1):i3
        }
        tup = (s1, s0)
        return d[tup]
    return mux_fn

def xor2(a,b):
    mux_fn = mux41(0,1,1,0)
    return mux_fn(a,b)

编辑:如果我想在Python中做一个查表的XOR,我会这样写。

_d_xor2 = {
    (0,0) : 0,
    (0,1) : 1,
    (1,0) : 1,
    (1,1) : 0
}

def xor2(a,b):
    tup = (a, b)
    return _d_xor2[tup]

我们只需构建一次查找字典,然后直接在 xor2() 中使用它。其实在 xor2() 中不一定需要明确的临时变量,但这样可能会更清晰。你也可以直接这样做:

def xor2(a,b):
    return _d_xor2[(a, b)]

你更喜欢哪种方式?

当然,由于Python内置了XOR运算符,你也可以这样写:

def xor2(a,b):
    return a ^ b

如果我真的在写这个,我可能会添加错误处理,或者让它处理 bool 值。

def xor2(a,b):
    return bool(a) ^ bool(b)

编辑:我刚想到一件事。在Python中,有个规则是“逗号构成元组”。元组的括号有时是可选的。我刚检查了一下,省略括号在字典查找中也能正常工作。所以你可以这样做:

def xor2(a,b):
    return _d_xor2[a, b]

这样也可以正常工作。这可能有点太复杂了?如果我在别人的代码中看到这个,我会感到惊讶。

12

这里的 (a, b) 实际上是你在 mux41 函数中返回的 lambda 函数的输入。

你的 mux41 函数返回了一个 lambda 函数,这个函数看起来是根据传给 mux41 函数的输入,从一个字典中返回一个值。你需要第二个输入来指定你想要返回哪个值。

这实际上是等价于:

def xor2(a,b):
    f = mux41(0,1,1,0)
    return f(a,b)

撰写回答