函数是组织好的,可重复使用的,用来实现单一功能的代码段
函数能提高应用的模块性,和代码的重复利用率。我们已经知道Python提供了许多内建函数,比如print()、input()、int()等。但你也可以自己创建函数,这被叫做自定义函数。
1、定义函数
定义函数的规则如下:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数内容以冒号 : 起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
我们来写个例子吧
# -*- coding: utf-8 -*-
def max_number(a, b):
"""
比较数字的大小
:param a:
第一个数字
:param b:
第二个数字
:return:
返回较大的数字
"""
if a > b:
return a
else:
return b
if __name__ == '__main__':
result = max_number(6, 8)
print(result)
输出结果为 8
例子中定义了函数 max_number,并通过(“”" “”")给函数添加了注释,方便调用函数的人了解函数的功能和参数,函数注释非常有用,在日常工作中,规范的函数注释是必须的。定义好的函数在python启动入口进行了调用,传入了参数6和8,并打印了返回的结果。
2、参数传递
2、1值参数与引用参数
当你往函数传递参数时候,需要注意,传递的参数是值参数还是引用参数,简单点说:
- 引用参数传递到函数中去后,参数的内容在函数中有变动,就会影响传递进函数的对象本身。
- 值参数传递到函数中去后,参数的值在函数中有变动,不会影响传递进函数的对象本身。
可能听起来有点不好理解,我们还是举个例子吧
# -*- coding: utf-8 -*-
def change_value(input_value):
print("函数内部正在给参数赋值")
input_value = 10
print(input_value)
if __name__ == '__main__':
a = 6
change_value(a)
print("a的值为")
print(a)
例子中我们有个函数用来给传入的参数赋值,a 原来的值为6,把a传入函数中,那结果a的值是什么呢?我们一起来看看输出结果
函数内部正在给参数赋值
10
a的值为
6
结果是不是和你像的一样?a的值没有改变,还是6,就算它被传入到函数中去,在函数中被赋值为10,神奇吧?
其实 这类被传入到函数中,无论函数对它做什么操作都不会影响原来值的对象叫做值参数,值参数传递的是值的本身,当它被传入函数,也仅仅是传入了一个值给函数,并不是把对象本身传到函数里面,所以 函数无论做什么操作都不会影响原来传值的对象,在python中值参数有哪些呢?有数字(numbers)、字符串(Strings)、元组(tuples)等
2、2引用参数
我们也举一个引用参数的例子吧,看看引用参数会不会影响传参对象的内容呢?
# -*- coding: utf-8 -*-
def change_list(input_list):
input_list.append(9)
print("函数内取值: ", input_list)
if __name__ == '__main__':
my_list = [1, 2, 3]
change_list(my_list)
print("函数外取值: ", my_list)
函数change_list接收一个列表对象,并给列表增加一个元素9,那结果会影响传入的对象吗?
输出结果为
函数内取值: [1, 2, 3, 9]
函数外取值: [1, 2, 3, 9]
从结果能看出来,函数的操作改变了传入参数的对象my_list,这就是引用参数,传入的是对象的引用,对传入参数的对象本身是有影响的,那有哪些是引用参数呢?比如 列表(list)、字典(dict)等。
3、参数
3、1必要参数
所谓的必要参数也就是你在调用函数的时候必须传入值的参数,如果 你不传就会出现语法错误,举个例子吧
def printme( str ):
"打印任何传入的字符串"
print (str)
return
# 调用 printme 函数,参数str你不传值,就会报错
printme()
3、2关键字参数
当函数有一个或多个参数的时候(一个参数的时候没有什么意义,用关键字参数指定参数名称是多此一举),你可以通过指定参数名称的方式传入参数,例如
def printinfo( name, age ):
"打印任何传入的字符串"
print ("名字: ", name)
print ("年龄: ", age)
return
#调用printinfo函数
printinfo( age=50, name="hello" )
例子中我们通过参数名称来指定传入的值和顺序,函数默认是参数name在前,age在后,我们可以通过指定的方式以任意顺序传入值。
3、3默认参数
调用函数时,如果没有传递参数,则会使用默认参数。这要求你在函数定义的时候给参数一个默认值
以下实例中如果没有传入 age 参数,则使用函数定义的默认值35
def printinfo( name, age = 35 ):
"打印任何传入的字符串"
print ("名字: ", name)
print ("年龄: ", age)
return
#调用printinfo函数
printinfo( age=50, name="hello" )
print ("------------------------")
printinfo( name="hello" )
输出结果为
名字: hello
年龄: 50
------------------------
名字: hello
年龄: 35
3、4不定长参数
当你定义函数的时候,对某些传入参数的数量不确定,你可以使用不定长参数,不定长参数有两种形式,第一种在参数前面加*,说明这个参数的长度可以是零个或多个,结果会以元组的形式传入函数中,第二种 在参数前面加**,也就是两个星号,作用和第一种一样,只是会以字典的形式传入函数中,我们一起来看看例子吧
def print_info(first, *vartuple ):
print("输出: ")
print(first)
for var in vartuple:
print(var)
if __name__ == '__main__':
print_info(1)
print("------------------------")
print_info(2, 3, 4, 5)
输出结果为,从结果可以看出,只要该函数第一个参数有值即可调用,后面任意长度的常数都被归纳到第二个参数中以元组的形式传入函数中。
输出:
1
------------------------
输出:
2
3
4
5
第二种形式其实也是一样的,只是在函数定义的时候需要用两个星号,在传入参数的时候需要用字典的形式,例子如下
def print_info(first, **vardict):
print("输出: ")
print(first)
for var in vardict.values():
print(var)
if __name__ == '__main__':
print_info(1)
print("------------------------")
print_info(2, a=3, b=4, c=5)
输出结果也和上面一样
参数中星号 * 可以单独出现,例如:
def f(a,b,*,c):
return a+b+c
如果单独出现星号 *,则星号 * 后的参数必须用关键字传入,调用f函数的时候参数c必须是关键字传参,也就是 f(1,2,c=3)
4、匿名函数
Python 使用 lambda 表达式来创建匿名函数。所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数
语法
lambda 函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
其中的[]是可选的意思,也就是说匿名函数的定义是以lambda开头, 后面可以有任意个参数,然后用:分隔表达式,我们举个例子好了
x = lambda a : a + 10
print(x(5))
结果输出
15
5、None值
如果你希望变量中存储的东西不会与一个真正的值混淆, 这个没有值的值就可能有用。在 Python 中有一个值称为 None,它表示没有值。 None 是 NoneType 数据类型的唯一值(其他编程语言可能称这个值为 null、 nil 或 undefined)。就像布尔值 True和 False 一样, None 必须大写首字母 N。
6、函数返回值
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带返回值的函数, Python 都会在末尾加上 return None。我们来个例子吧
def sum( arg1, arg2 ):
total = arg1 + arg2
return total
# 调用sum函数
total = sum( 10, 20 )
print ("结果为 : ", total)
输出如下
结果为 : 30
输出值为30,如果 我们去掉return total
def sum( arg1, arg2 ):
total = arg1 + arg2
# 调用sum函数
total = sum( 10, 20 )
print ("结果为 : ", total)
输出结果为
结果为 : None
7、局部与全局作用域
在被调用函数内赋值的变元和变量,处于该函数的“局部作用域”。在所有函数之外赋值的变量,属于“全局作用域”。处于局部作用域的变量,被称为“局部变量”。处于全局作用域的变量,被称为“全局变量”。一个变量必是其中一种,不能既是局部的又是全局的。
一个函数被调用时, 就创建了一个局部作用域。在这个函数内赋值的所有变量,存在于该局部作用域内。该函数返回时,这个局部作用域就被销毁了, 这些变量就丢失了
我们要关注作用域以下几点:
- 全局作用域中的代码不能使用任何局部变量;
- 局部作用域可以访问全局变量;
- 一个函数的局部作用域中的代码,不能使用其他局部作用域中的变量。
- 如果在不同的作用域中,你可以用相同的名字命名不同的变量。也就是说,可以有一个名为 sum 的局部变量,和一个名为 sum 的全局变量。
注意:在函数中最好不要去依赖全局变量,这样就破坏了函数的封装性,让函数和全局变量耦合在一起了。
如果 你在函数中实在是想用全局变量,使用global关键字标明,示例如下
# -*- coding: utf-8 -*-
def test_global():
global ages;
return ages + 1
if __name__ == '__main__':
ages = 9
result = test_global()
print(result)
在函数test_global中我们使用global标明ages为全局变量