Python - 函数参数
位置参数
先看两个普通的函数参数
1 | def foo(): |
foo函数没有任何参数, bar函数接受两个参数
如果给foo函数传参数会怎样,比如foo(5, "str")
?
1 | TypeError: foo() takes 0 positional arguments but 2 were given |
同样地,给bar函数传大于或小于两个参数,也会报同样的错。
因此,如果限定了函数签名,则必须按照指定的签名传入参数。
如果给bar传入两个并不能相加的参数会怎样,比如bar(5, "str")
?
1 | TypeError: unsupported operand type(s) for +: 'int' and 'str' |
限定类型
那么,是否可以像静态语言C++一样限定类型呢?
从Python 3.5 开始,我们可以像下面这样限定类型。
1 | def greeting(name: str) -> str: |
除了基本的类型外,还可以限定类型为函数指针,泛型,自定义类型等等。具体玩法在这里。
默认参数
我们也可以给函数参数赋默认值。例如:
1 | def bar(a: int, b: int = 5) -> int: |
那我们可以定义成def bar(a: int = 5, b: int) ->int
吗?
1 | SyntaxError: non-default argument follows default argument |
不能。
任何参数都可以由默认值,但是一旦有了默认参数,其右边的所有参数也必须具有默认值。
关键词参数
Python允许使用关键字参数调用函数。例如:
1 | def bar(a: int, b: int) -> int: |
但在关键字参数之后放置位置参数将导致错误。例如:
1 | r = bar(a=6, 9) |
有没办法限制必须用关键词参数呢?有的。例如:
1 | def bar(a: int, *, b: int) -> int: |
可变参数
可否像其他语言一样玩可变参数呢?可以!可变参数可以是位置参数,也可以是关键词参数。例如我们常在开源项目中看到这样的定义:
1 | def foo(*args, **kwargs): |
上面的例子中,args收集所有的可变位置参数为一个元组,kwargs收集所有的关键词参数为一个字典。
需要注意的是,关键词参数不能写在位置参数前面。