函数的定义
函数, 在几乎所有语言中, 都是一个主要的代码结构
你可以将函数理解为定义一个代码块来执行特定的操作
一个函数由下面几个部分组成
- 函数名
- 参数
- 返回值
- 函数体
def a_test_function(name: str):
"this is a test function "
print("hello " + name)
a_test_function("world")
hello world
组成部分 | 含义 |
def | def 为python的关键词, 用于定义一个函数, 所有函数的定义都是通过def关键词来申明 |
a_test_function | 申明函数名为a_test_function, 后续函数的调用都通过a_test_function来进行调用 |
name: str | 申明函数的参数名为name, 类型为字符串类型,指定类型是可选的 |
“this is a test function “ | 函数体的第一行语句为字符串时, 该字符串就是文档字符串,也称为 docstring |
print(“hello ” + name) | 函数体,函数体的定义需要缩进, 也是具体的执行代码, 这边a_test_function函数做的事情就一起, 就是打印hello name |
a_test_function("world")
, 是函数的调用, “world”用于指定参数name为world
所以函数执行的结果是打印hello world
python支持按参数名指定参数和按位置指定参数, 所以上述代码调用等价于
a_test_function(name="world")
, 在这个调用中, 直接显示的指定name参数的值为world
作用域
函数在其函数体内有自己的作用域名, 其中, 参数的作用域只在函数体内, 也就是函数的参数只能在函数体内访问, 在其他地方不能访问
函数在访问一个变量时, 会先在函数局部作用域中查找, 然后在全局作用域中查找, 最后在内置符号表中查找
所以, 函数可以访问和修改函数外部的变量, 但是建议不要直接访问函数外部的变量, 这样会使代码的可读性变得很差, 除非在变量的定义是就定义成了global或者nonlocal变量
global标识函数内的变量为全局变量
x = 10 # 全局变量
def modify_global():
global x # 声明使用全局变量 x
x += 5
print("Inside function:", x)
modify_global()
print("Outside function:", x)
Inside function: 15
Outside function: 15
nonlocal标识函数内变量为上层函数的变量
def outer():
x = 10 # 外层函数变量
def inner():
nonlocal x # 声明修改外层函数的 x
x += 1
print("Inner x:", x)
inner()
print("Outer x:", x)
outer()
Inner x: 11
Outer x: 11
函数的返回值
在Python中, 所有的函数都有返回值, 在没有显示的指定返回值时, 也就是没有在函数内部调用return xx
时, python 会隐式的定义函数的返回值为None
函数的参数
默认参数
默认参数是指, 在函数定义的时候给定一些参数以默认值, 当函数调用时没有指定对应参数值, 则使用默认值
def default_arg_function(first_name='dot', last_name = 'k'):
print(first_name + last_name)
default_arg_function()
输出:
dotk
default_arg_function('hello', 'world')
输出:
helloworld
在定义默认参数时, 需要有一个原则, 就是默认参数都在函数的末尾, 也就是, 所有有默认值的参数都要跟在没有默认值参数的后面
下面这个例子, 就会报语法错误
>>> def default_arg_function(first_name='dot', last_name):
File "<stdin>", line 1
def default_arg_function(first_name='dot', last_name):
^
SyntaxError: non-default argument follows default argument
>>>
>>> #将默认参数移到末尾则不会报错
>>> def default_arg_function(first_name, last_name='k'):
... print(first_name + last_name)
...
>>>
关键词参数
python中函数的调用, 除了直接通过位置来确定调用参数以外, 还可以通过关键词的方式确定函数的参数, 也就是以参数名=参数值
的方式指定参数值
首先定义一个函数
def test(name, age, gender):
print(name, age, gender)
可以通过位置指定参数的方式调用: test('点点K', 18, ‘male’)
也可以通过关键词指定的方式进行调用: test(name='点点K', gender=‘male’, age=18)
, 我们注意到, 在进行关键词指定时, 参数的位置已经不在重要了, 可以跟函数定义的位置不一致
我们也可以通过混合的方式来进行调用: test('点点K', gender=‘male’, age=18)
, 使用位置参数指定name为点点K, 使用关键词参数指定gender和age分别为male和18
以上三种调用方式都是等价的
特殊参数
在python的函数定义中, 当最后一个参数为**name时, 接收的是所有未定义的关键词参数, 在**name前的*name, 接收的是所有未定义的位置参数
*name 返回一个元组, 元组的内容是调用时指定的未定义的位置参数
**name返回一个字典, 内容时调用时指定的未定义的关键词参数
>>> def test(name, *position_argvs, **keywords_argvs):
... print(name, position_argvs, keywords_argvs)
...
>>> test('点点K', 'hello', 'tuple', say='hello', hi='world')
点点K ('hello', 'tuple') {'say': 'hello', 'hi': 'world'}
解包调用
可以通过解包tuple或list来指定位置参数完成函数调用
通过*
将列表或者元组解包, 从而指定位置参数完成函数调用
>>> def test(say, hi):
... print(say + " " + hi)
...
>>> args = ('hello', 'world')
>>> test(*args)
hello world
以此类推, 可以解包字典来指定关键词参数完成函数的调用
通过**
完成字典的解包, 从而指定关键词参数完成函数的调用
>>> def test(say, hi):
... print(say + " " + hi)
...
>>> args = {'say': 'hello', 'hi':'world'}
>>> test(**args)
hello world
解包的操作跟好跟特殊参数相呼应
在函数体内是, 使用*name获取未定义的位置参数得到一个元组, 在调用时使用*name解包对应的元组或list完成位置参数的指定
函数体内**name获取未定义的关键词参数得到一个字典, 在调用时使用**name解包对应的字典来完成关键词参数的指定
lambda 表达式
lambda表达式是python中用与定义匿名函数的语法糖, 可以很方便的定义一个简单的函数
具体的使用方式是 lambda arg…: dosomething, :前用于定义参数, 多个参数用,分割, :后用于定义函数体
比如
f = lambda x, y: x+y
f(1, 2)
# 结果
3