目录
函数的定义
定义函数的关键字def。函数名,本例函数名是test。小括号里面是参数。冒号后缩进的代码块是函数内容。函数的注释用""",使用双引号是为了规范。return返回值。pass说明函数结束,其实pass不加也没问题,但是为了规范还是写上吧。
Python解释器逐行解释,如果函数test定义一次以后,再定义一个函数test,那么就test就以最后一次定义的为准。
def test(x):
"""
function test
:param x: 整数
:return: 返回x的立方值
"""
y = x ** 3
return y
pass
def test():
"""
function test
这就重新定义了函数test
:return: 9527
"""
return 9527
pass
val = test()
print(val)
# 9527
函数的返回值
Python的返回值和Java一样也是只有一个返回值。因为Python有了元组这个容器类型,所以多个返回值可以被转换为一个元组返回。看起来可以返回多个值,而且实际上你也可以这么用。
def func01():
"""
如果没有返回值,那么返回的是None
:return: None
"""
msg = "func01"
print(msg)
def func02():
"""
返回一个值
:return: msg
"""
msg = "func02"
print(msg)
return msg
def func03():
"""
如果返回多个值,那么返回的是这多个值组成的元组。
实际上是返回一个值,元组。但是你可以用多个变量来接收这个元组的元素。
:return:
"""
msg = "func03"
print(msg)
return msg, [11, 22, 33], 28, "Kevin"
t1 = func01()
t2 = func02()
t3 = func03()
val, li, num, name = func03()
print(t1)
print(t2)
print(t3)
print(val, li, num, name)
# None
# func02
# ('func03', [11, 22, 33], 28, 'Kevin')
# func03 [11, 22, 33] 28 Kevin
函数的参数
参数的传递
函数的参数分为实参和形参。
func04的参数xyz都是形参。形参只在函数被调用时分配内存空间,函数调用结束以后内存空间就被释放。
函数传参可以传位置参数,就是按照形参顺序传参,不能多也不能少。
函数传参可以传关键字参数,就是形参名=实参,顺序无所谓,不能多也不能少。
位置参数和关键字参数可以混搭使用。位置参数必须在关键字参数前面,传参总个数不能多也不能少。
def func04(x, y, z):
print(x, y, z, sep=",")
return
# 位置参数,按照顺序传参,不能多也不能少
func04(11, 22, 33)
# 关键字参数,按照关键字传参,顺序无所谓,不能多也不能少
func04(z=33, x=11, y=22)
# 位置参数和关键字参数可以混用
# 位置参数 必须在 关键字参数 前面,不能多也不能少
func04(11, 22, z=33)
参数的默认值
函数的参数可以有默认值。非默认值参数必须放在默认值参数前面。调用时,非默认参数必须传值,默认值参数可以不传值。参数不用默认值时,用关键字参数指定哪个参数不用默认值。
def func05(app, db="mysql", os="linux"):
"""
非默认值参数放在默认值参数前面。
默认数据库是mysql,默认操作系统是linux。
:param app: 应用
:param db: 数据库
:param os: 操作系统
:return: None
"""
print("%(app)s, %(db)s, %(os)s." % ({"app": app, "db": db, "os": os}))
pass
# 默认值参数不用传输
# discuzz, mysql, linux.
func05("discuzz")
# 参数不用默认值时,最好用关键字参数,指定哪个参数不是默认的值
# httpd, mysql, freebsd.
func05("httpd", os="freebsd")
可变长参数
传入多个参数,*对应列表,**对应字典。
函数参数加上*args,函数就可以接收多个位置参数,按照Python规则*args就这么写。*args接收位置参数,除去前面的位置参数,多出来的被处理成元组args。如果传入的是列表,那么列表就是元组args的一个元素。如果传入的*列表,那么就把列表的元素处理成元组args的元素。
def func06(x, y, *args):
"""
*args接收位置参数,将多个参数处理成元组。
此时,函数可以接收多个参数,出去前面的位置参数,后面的多个参数处理成元组
如果传入的是个列表,那么这个列表就是元组args的一个元素。
如果传入的列表元素都变成args的元素,那么传参时需要加*。*对应列表
:param x:
:param y:
:param args:
:return:
"""
print(x)
print(y)
print(args)
pass
# 1
# 2
# ()
func06(1, 2)
# 1
# 2
# (3, 4, 5, 6)
func06(1, 2, 3, 4, 5, 6)
# 1
# 2
# ([3, 4, 5, 6],)
func06(1, 2, [3, 4, 5, 6])
1
2
(3, 4, 5, 6)
func06(1, 2, *[3, 4, 5, 6])
函数加上**kwargs,函数就可以接收多个关键字参数,按照Python规则就这么写。接收的多个关键字参数被处理成字典kwargs。如果要传入字典的话,字典前面加上**。
def func07(x, y, **kwargs):
"""
*kwargs接收关键字参数,将多个关键字参数处理成字典。
此时,函数可以接收多个关键字参数,除去前面的位置参数,后面的多个关键字参数被处理成字典
如果传入的是字典,需要在字典前面加**
:param x:
:param y:
:param kwargs:
:return:
"""
print(x, y)
print(kwargs, kwargs.get("k1"))
pass
# 1 2
# {'k1': 'v1', 'k2': 'v2'} v1
func07(1, 2, k1="v1", k2="v2")
# 1 2
# {'k1': 'v1', 'k2': 'v2'} v1
func07(1, 2, **{"k1": "v1", "k2": "v2"})
如果函数参数加上了*args和**kwargs,那么这个函数就可以接收任意的参数了。这样有利于未来的扩展。接收的参数怎么处理是函数实现的问题。
def func08(x, y, *args, **kwargs):
"""
现在这个函数牛逼了
:param x:
:param y:
:param args:
:param kwargs:
:return:
"""
print(x, y)
print(args)
print(kwargs, kwargs.get("k1"))
pass
# 1 2
# (3, 4, 5, 6)
# {} None
func08(1, 2, 3, 4, 5, 6)
# 1 2
# ()
# {'a': 5, 'b': 9} None
func08(1, 2, a=5, b=9)
# 1 2
# (3, 4, 11, 22, 33, 44)
# {'k1': 'v1', 'k2': 'v2', 'k3': 9527} v1
func08(1, 2, 3, 4, *[11, 22], *[33, 44], **{"k1": "v1", "k2": "v2"}, k3=9527)
全局变量与局部变量
全局变量作用于全局。局部变量作用于代码块。执行函数时,先找局部变量,局部变量找不到再找全局变量。如果要直接访问全局变量,那么要用global声明。Python编程规范,全局变量全部大写,局部变量全部小写,这样以后就不会出现变量名重合的情况了。
name = "Kevin"
name1 = "Tom"
def change_name():
global name
name = "Alice"
name1 = "Jerry"
print(name, name1)
pass
# Alice Jerry
# Alice Tom
change_name()
print(name, name1)
函数嵌套定义
函数里面还可以再定义函数。如果出现global,那么global变量就是全局变量。这段代码func12将全局变量name的值从Able改成了Charlie。
name = "Able"
def func11():
name = "Baker"
def func12():
global name
name = "Charlie"
pass
func12()
print(name)
pass
print(name)
func11()
print(name)
函数里global只的就是全局变量,而另一个关键字nonlocal指的是上一层的变量。这段代码,func12里面将func11的局部变量name的值从Baker改为Charlie。
name = "Able"
def func11():
name = "Baker"
def func12():
nonlocal name
name = "Charlie"
pass
func12()
print(name)
pass
print(name)
func11()
print(name)
# Able
# Charlie
# Able
风湿理论——函数即变量
Python的风湿理论?靠,什么鬼名字。这里的意思是函数都可以看成是函数名的字符串。只要在这个字符串里面的变量或者函数曾经出现在内存中,就可以找到,继续执行不会报错。
这个例子中func14虽然定义在func13之后,但是根据风湿理论,程序逐行执行,func13和func14都会先作为变量保存在内存中。调用func13时,执行func13代码块,遇到调用func14,因为func14已经存在了,找得到,所以不会报错。
def func13():
print("from func13")
func14()
pass
def func14():
print("from func14")
pass
# from func13
# from func14
func13()