函数调用

函数名之后带一个圆括号,圆括号内,根据形参的类型(详见函数形参),给函数传递相应的实参,即可调用函数,执行函数体中的代码。

函数调用传递的实参分为:位置参数关键字参数

  • 位置参数: 调用函数时,不带标识符(例如 name=)直接按形参位置传递给函数的参数。位置参数可使用 * 将可迭代对象的元素拆包传入函数,但元素个数不能多于可接收位置参数的形参个数,除非有接收多个位置参数的可变位置形参。
def f(a,b=None,*c,d=None):
    print(f'a={a},b={b},c={c},d={d}')
    
f(*[1,2,3,4,5]) # d 只能接收关键字参数
a=1,b=2,c=(3, 4, 5),d=None
def f(a,b=None,*,c=None):
    print(f'a={a},b={b},c={c}')
    
f(1,2)
f(1,2,3) # c 只能接收关键字参数
a=1,b=2,c=None


---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-2-9cc318bcfef7> in <module>
      2     print(f'a={a},b={b},c={c}')
      3 f(1,2)
----> 4 f(1,2,3)


TypeError: f() takes from 1 to 2 positional arguments but 3 were given
  • 关键字参数: 函数调用中前面带有标识符(例如 name=)传递给函数的参数。关键字参数可以使用 ** 将字典里的元素传入函数,但元素个数不能多于可接收关键字参数的形参个数。关键字参数的标识符或字典的键,必须与可接收关键字参数的形参的名称相同,除非有可接收任意关键字参数的可变关键字形参。
def f(a,/,b=None,*,c=None):
    print(f'a={a},b={b},c={c}')
    
f(1,c=3,b=2) # a 仅限位置传参
f(a=1,c=3,b=2)
a=1,b=2,c=3


---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-7-3c39aaeac558> in <module>
      3 
      4 f(1,c=3,b=2) # a 仅限位置传参
----> 5 f(a=1,c=3,b=2)


TypeError: f() got some positional-only arguments passed as keyword arguments: 'a'
def f(a,/,b=None,**c):
    print(f'a={a},b={b},c={c}')

# a 仅限位置,b 没有对应的名称,因此全部传给 c
f(1,**{'a':1,'d':4,'c':3})
a=1,b=None,c={'a': 1, 'd': 4, 'c': 3}

位置参数必须在关键字参数前面:

def f(a,b=None,**c):
    print(f'a={a},b={b},c={c}')

f(b=2,1)
  File "<ipython-input-13-59f3b615f9f3>", line 4
    f(b=2,1)
          ^
SyntaxError: positional argument follows keyword argument

位置参数的位置不能传错,关键字参数的则可以任意位置:

def f(a,b=None,/,c=None,**d):
    print(f'a={a},b={b},c={c},d={d}')

f(1,2,c=3,d=4)
f(2,1,d=4,c=3,e=5)
a=1,b=2,c=3,d={'d': 4}
a=2,b=1,c=3,d={'d': 4, 'e': 5}

标注并不影响传参规则,但按照标注传参是更明智的做法:

def f(a:int,b:str='b')-> str:
    print(a*b)
    
f(2,'hi')
f(2,3)
hihi
6