说明
Python 教程正在编写中,欢迎大家加微信 sinbam 提供意见、建议、纠错、催更。
一般情况下,我们写的函数都需要定义参数。为了让我们写的函数更加通用,满足多种用途,Python 的函数支持我们灵活的参数定义。
无参数
如果让函数直接做一个事情,不需要给它任何要求,就不需要设置参数:
def say():
print('我很帅')
形参和实参
它们的定义为:
形参(parameters):定义时参数名称
实参(arguments):实际合入的值
可以简单理解成一个是变量一个是值,如:
# 定义
def foo(name, age=18, boy=True, **kwargs):
pass
# 调用
foo('tom', age=20, city='shanghai')
其中,name、age 等是形参,'tom'、20 是实参。
默认值参数
我们在定义函数时可以给一参数给定默认值,在调用的时候就不需要传此参数了,在有需要的时候再传。
还是上例的函数, age 和 boy 有默认值,我们不需要传,直接传 name 的:
foo('小刚')
foo('小刚', 22) # 也可以给默认参数传值
foo('小刚', age=22) # 同上
注:
多个默认值参数如果不指定形参需要按顺序传递变量
如果同时有默认值和没有默认值的的参数,没有默认值的必须在有默认值的前边,否则会报错:
SyntaxError: non-default argument follows default argument
同时,建议设置默认值参数为不可变对象,如整数、浮点数、字符串等。
位置参数
指在固定位置的参数,在调用时按位置顺序传入。
def foo(x, y):
return x-y
# 调用
foo(10, 8) # 2
上例中位置不同会得到不同的值。
关键字参数
调用函数时我们可以使用调用关键字参数,格式为 关键字=参数值,这样就不用关心顺序问题了。
def say(name, age=18, words='hello'):
print(f'{age}岁的{name}说:{words}')
# 调用
say(name='tom', age=20) # 20岁的tom说:hello
关键字参数后面必须都是关键字参数:
say('tom', age=20) # 20岁的tom说:hello
say('tom', age=20, 'good') # 报错
可变参数
有时候我们不确定参数的数量,可使用可变参数,类似 **kwargs。其中:
*args 一个星号,以元组(tuple)的形式导入
**kwargs 两个星号,以字典的形式导入
args 和 kwargs 是习惯写法,可以用其他变量名称
def foo(*t):
print(t)
# 调用
foo(1) # (1,)
foo(1,4,5,6) # (1, 4, 5, 6)
def foo(**d):
print(d)
# 调用
foo(a=1) # {'a': 1}
foo(a=1,b=4,c=5) # {'a': 1, 'b': 4, 'c': 5}
可变参数与其他类型的参数混用时,采用元组拆包(解包)的原则。
def foo(a, b,*c, d):
print(a,b, c, d)
# 调用
foo(1,2,3,4,5,d=6) # 1 2 (3, 4, 5) 6 d 要用关键字传入
可以通过 ** 用字典传递关键字参数:
def say(name, age=18, words='hello'):
print(f'{age}岁的{name}说:{words}')
# 调用
d = {'name':'tom', 'age':20, 'words': 'hello'}
say(**d) # 20岁的tom说:hello
独立星号
函数的多个参数中间有一个单独的星号*分隔,星号后面为命名关键字参数,星号本身不是参数,命名关键字参数,在函数调用时必须带参数名字进行调用。如:
def my(x, y, *, name, age):
print(x, y, name, age)
# 不指定 name 和 age 参数名会报错
my(1,2,'lily',9)
# TypeError: my() takes 2 positional arguments but 4 were given
# 指定名正常
my(1,2,name='lily',age=9)
# 1 2 lily 9
最后一个斜线参数
函数参数列表中的斜杠表示在它之前的形参是仅限位置形参。函数参数最后一个斜线表示该函数只接收位置参数而不接收关键参数,但是在Python中并不允许定义这样的函数,这样的函数一般是用C语言开发的内置函数或特定对象的方法,更加详细的资料可以查阅“Argument Clinic”有关资料。
# divmod(x, y, /) Return the tuple (x//y, x%y)
divmod(x=3, y=4)
# TypeError: divmod() takes no keyword arguments
divmod(3,4)
# (0, 3)
参数类型检查
python 3.5 后引入了参数类型注解,但没有强制作用:
# 对 a, b 和返回值的类型进行检查,为 int 类型
def add(a:int, b:int)->int:
return a + b
形参
function (或方法)定义中的命名实体,它指定函数可以接受的一个 argument (或在某些情况下,多个实参)。有五种形参:
positional-or-keyword:位置或关键字,指定一个可以作为 位置参数 传入也可以作为 关键字参数 传入的实参。这是默认的形参类型,例如下面的 foo 和 bar:
def func(foo, bar=None): ...
positional-only:仅限位置,指定一个只能通过位置传入的参数。 仅限位置形参可通过在函数定义的形参列表中它们之后包含一个 / 字符来定义,例如下面的 posonly1 和 posonly2:
def func(posonly1, posonly2, /, positional_or_keyword): ...
keyword-only:仅限关键字,指定一个只能通过关键字传入的参数。仅限关键字形参可通过在函数定义的形参列表中包含单个可变位置形参或者在多个可变位置形参之前放一个 * 来定义,例如下面的 kw_only1 和 kw_only2:
def func(arg, *, kw_only1, kw_only2): ...
var-positional:可变位置,指定可以提供由一个任意数量的位置参数构成的序列(附加在其他形参已接受的位置参数之后)。这种形参可通过在形参名称前加缀 * 来定义,例如下面的 args:
def func(*args, **kwargs): ...
var-keyword:可变关键字,指定可以提供任意数量的关键字参数(附加在其他形参已接受的关键字参数之后)。这种形参可通过在形参名称前加缀 ** 来定义,例如上面的 kwargs。
形参可以同时指定可选和必选参数,也可以为某些可选参数指定默认值。