5

多年来,我注意到我遇到的各种 Python 中的“通配符”变量。我假设它像 Haskell 一样工作:允许您将变量放在形式参数中需要的位置,但不绑定它。

例如,当我不需要其中一个变量时,我在元组解包赋值的左侧使用了它。

例如:

_, extension = os.path.splitext(filename)

所以当我今天写了类似的东西时:

(lambda (x,_,_): x)((1,2,3))

IE 我尝试绑定下划线两次,收到语法错误。我惊讶地发现 _ 确实是一个实变量:

(lambda (x,_,z): _)((1,2,3))
> 2

看起来_只是一个变量名,就像其他变量名一样。

根据第一个示例,是否有我可以随意使用的真正通配符变量(即能够在元组解包分配中使用多个)?

4

5 回答 5

4

Python 中没有通配符变量。

我试图劝阻人们在_相当长的一段时间内不要将其用作变量名。您不是第一个误_认为某种特殊语法的人,因此最好不要将其_用作变量名以避免这种混淆。如果曾经有一个“约定”_用作一次性变量名,那么这个约定是错误的。

除了它引起的混乱之外,还有更多的问题。例如,在交互式解释器中与常见的 gettext 别名_发生冲突。_

关于lambda表达式,我只是lambda x, *args: ...用来忽略除第一个参数之外的所有参数。在其他情况下,我会使用明确说明我不想使用它们的名称,例如dummy. 在range()s 循环的情况下,我通常使用for i in range(n)并且根本不使用i.

编辑:我刚刚注意到(通过查看其他答案)您在参数列表中使用元组解包,因此lambda x, *args: ...不能解决您的问题。Python 3.x 中删除了参数列表中的元组解包,因为它被认为是一个太晦涩的功能。最好改用mipadi 的答案

于 2011-11-01T16:16:49.030 回答
3

不,Python 没有任何等效于 Haskell 的_. Python 中的约定是_用于“一次性”变量,但它是一个实际的变量名,正如您所发现的,您不能在同一上下文中使用它两次(如 lambda 参数列表)。

在您提供的示例中,我只使用索引:

lambda tup: tup[0]

或者

lambda tup: tup[1]

不那么漂亮,但更好的方法之一。

于 2011-11-01T16:12:33.097 回答
3

并不真地。Python 不是 Haskell。Map、apply、reduce 和 lambda 是一种二等公民,尽管在 itertools 中有一些有趣的东西。

除非您需要使用单行 lambda,否则正确的方法是:

def f(x, *args, **kwargs):
    return x

*args参数允许您使用任意数量的未命名参数(将作为一个名为 的元组提供args)。额外的命名参数将在一个名为kwargs.

我认为在 lambda 中没有任何方法可以做到这一点,但通常没有必要。函数声明可以去任何地方。请注意,如果将函数定义放在另一个函数(或循环)中,您会做一些有趣/邪恶的事情:

def make_func(s):
    def f(*trash, **more_trash):
        print s
    return f

f1 = make_func('hello')
f2 = make_func('world')
f1(1,2,'ham','spam')
f2(1,2,a=1,b=2)

将输出:

>>> hello
>>> world

正如@rplnt 指出的那样,对于循环,这将是不同的:

funcs = []
for s in ('hello','world'):
    def f():
        print s
    funcs.append(f)

for f in funcs:
    f()

将输出:

>>> world
>>> world

因为循环只有一个命名空间。

于 2011-11-01T16:14:54.647 回答
2

这是可能的,有一个小技巧:

class _: 
    def __eq__(x,y): return true
_=_() #always create a new _ instance if used, the class name itself is not needed anymore

[(a,b) for (a,_,_,b) in [(1,2,3,4),(5,6,7,8)]]

[(1, 4), (5, 8)] 

我经常使用它,因为它使代码更优雅,这是 Python 中 Haskells 美的一部分。

于 2013-01-14T20:44:35.893 回答
1

简短的回答是否定的。可以遵循您现有的约定。那是

(lambda (x, _1, _2): x)((1,2,3))
于 2011-11-01T16:14:06.597 回答