Python中的通配符?

时间:2011-11-01 16:03:55

标签: python pattern-matching tuples wildcard iterable-unpacking

多年来,我注意到我遇到的各种各样的Python中的'wildcard'变量。我认为它像Haskell一样工作:允许你在形式参数中放置一个变量,但不绑定它。

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

例如:

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

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

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

即。我试图绑定下划线两次,我收到了语法错误。我很惊讶地看到_确实是一个真正的变量:

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

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

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

5 个答案:

答案 0 :(得分:4)

Python中没有通配符变量。

我试图阻止人们在很长一段时间内使用_作为变量名称。您不是第一个将_误认为某种特殊语法的人,因此最好不要将_用作变量名来避免这种混淆。如果有一个“约定”使用_作为丢弃变量名称,则该约定被误导。

问题不仅仅是它引起的混乱。例如,_在交互式解释器中与_冲突,并与公共gettext别名冲突。

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

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

答案 1 :(得分:3)

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

在您给出的示例中,我只使用索引:

lambda tup: tup[0]

lambda tup: tup[1]

不是很漂亮,但是更好的方法之一。

答案 2 :(得分: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

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

答案 3 :(得分: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美的一部分。

答案 4 :(得分:1)

简短的回答是否定的。可以按照你现有的惯例。那是

(lambda (x, _1, _2): x)((1,2,3))