关于lisp:除了乘法和求幂之外,星号在Python中的作用是什么?

What does the asterisk do in Python other than multiplication and exponentiation?

本问题已经有最佳答案,请猛点这里访问。

在用python编写的peter norvig的lisp解释器(http://norvig.com/lispy.html)中,他将lisp的eval定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def eval(x, env=global_env):
   "Evaluate an expression in an environment."
    if isa(x, Symbol):             # variable reference
        return env.find(x)[x]
    elif not isa(x, list):         # constant literal
        return x                
    elif x[0] == 'quote':          # (quote exp)
        (_, exp) = x
        return exp
    elif x[0] == 'if':             # (if test conseq alt)
        (_, test, conseq, alt) = x
        return eval((conseq if eval(test, env) else alt), env)
    elif x[0] == 'set!':           # (set! var exp)
        (_, var, exp) = x
        env.find(var)[var] = eval(exp, env)
    elif x[0] == 'define':         # (define var exp)
        (_, var, exp) = x
        env[var] = eval(exp, env)
    elif x[0] == 'lambda':         # (lambda (var*) exp)
        (_, vars, exp) = x
        return lambda *args: eval(exp, Env(vars, args, env))
    elif x[0] == 'begin':          # (begin exp*)
        for exp in x[1:]:
            val = eval(exp, env)
        return val
    else:                          # (proc exp*)
        exps = [eval(exp, env) for exp in x]
        proc = exps.pop(0)
        return proc(*exps)

isa = isinstance

Symbol = str

我特别感兴趣的是这一行:

1
return proc(*exps)

exps中的星号究竟在做什么?


它解包参数

1
function(1,2,3)  ==  function(*[1,2,3])

它使得使用变量传递函数变得容易

1
2
args = [1,2,3]
func(*args) #much nicer than func(args[0],args[1],args[2],...)


在seqable对象解包它之前输入一个星号,如joran所示:

1
2
3
4
5
6
7
In [1]: def f(*args): return args

In [2]: f(1,2,3)
Out[2]: (1, 2, 3)

In [3]: f(*[1,2,3,4])
Out[3]: (1, 2, 3, 4)

(注:对*的第三个应用:在函数定义中,星号表示变长参数列表,所有参数都被打包成一个列表,argsIn [1]中)

同样值得注意的是,一个双星(**)可以打开字典:

1
2
3
4
5
6
7
8
9
10
In [5]: def g(foo=None, bar=42): return foo,bar

In [6]: g()
Out[6]: (None, 42)

In [7]: g(*[1,2])
Out[7]: (1, 2)

In [8]: g(**{'foo': 'FOO', 'bar': 'BAR'})
Out[8]: ('FOO', 'BAR')