Python基础(六):函数
定义函数
函数说明:
-
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
-
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
定义函数
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号 : 起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
无参无返回值
def fun():
语句
有参无返回值
def fun(x,y):
z=x+y
无参有返回值
def fun():
x=1
return x+1
有参有返回值
def fun(x,y):
return x+y
注:如果没有return
语句,函数执行完毕后也会返回结果,只是结果为None
。return None
可以简写成return
。
空函数
如果想定义一个什么事也不做的空函数,可以用pass语句。不知道怎么写函数的代码可以先放一个pass,让代码能运行起来
def nop():
pass
pass还可以用在其他语句,比如
if age>=18:
pass
多个返回值
return多个值,其实是返回一个元组
def move(x,y)
return x,y
print(move(1,2))
(1,2)
小结
-
定义函数时,需要确定函数名和参数个数;
-
如果有必要,可以先对参数的数据类型做检查;
-
函数体内部可以用
return
随时返回函数结果; -
函数执行完毕也没有
return
语句时,自动return None
。 -
函数可以同时返回多个值,但其实就是一个tuple。
调用函数
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
# 定义函数
def printme( str ):
# 打印任何传入的字符串
print (str)
return
## 调用函数
printme("我要调用用户自定义函数!")
printme("再次调用同一函数")
调用函数的时候,如果传入的参数数量不对,会报TypeError
的错误,并且python会明确告诉你参数数量错误
>>> abs(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (2 given)
调用函数的时候,如果传入的参数类型不能被函数所接受,也会报TypeError
的错误,并且给出错误信息:str
是错误的参数类型:
>>> abs('a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
>>> a = abs # 变量a指向abs函数
>>> a(-1) # 所以也可以通过a调用abs函数
1
函数的参数
必选参数
def foo(x, y, z):pass
默认参数
def foo(x=1):pass
- 假如不传
x
参数的话,x
默认是等于1 - 必选参数在前,默认参数在后,否则Python的解释器会报错
- 定义默认参数要牢记一点:默认参数必须指向不变对象!
可变参数(*
)
-
允许你传入0个或任意个参数(参数个数不确定)
-
不定长传参
- 定义:
def foo(*args):pass
- 调用:
foo(1,2,3,4,5)
- 定义:
-
传入元组或列表
- 定义:
def foo(*args):pass
- 调用:
foo(*(1,2,3,4,5))
orfoo(*[1,2,3,4,5])
- 定义:
关键字参数(**
)
- 允许你传入0或任意个含参数名的参数,(除必填参数外可增加其他参数名)
- 定义:
def foo(nam,age,**kwargs):pass
,其中kwargs
是一个字典 - 调用:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> foo('Jack', 24, **extra)
>>> foo('Jack', 24, city="hhh")
命名关键字参数
- 限制关键字参数的名字,就可以用命名关键字参数,例如,只接收
city
和job
作为关键字参数 - 和关键字参数
**kw
不同,命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数 - 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符
*
了 - 命名关键字参数必须传入参数名
- 命名关键字参数可提供默认值
- 定义:
def person(name,age,*,city='hhh',job):
print(name,age,city,job)
- 调用:
person('sxy',10,job='11')
参数组合
- 在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
- 定义:
def fun(parameter,*args,keyparameter,**kwargs):pass
- 调用
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
函数的递归
典型案例:斐波那契数列
def fib_recursion(idx):
if idx <= 2:
return 1
else:
return fib_recursion(idx-1) + fib_recursion(idx-2)
- 递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰
- 必须设置函数终止条件
- 使用递归函数需要注意
防止栈溢出
。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
尾递归
- 通过尾递归解决递归调用栈溢出
- 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式
列如:计算阶乘n! = 1 x 2 x 3 x ... x n
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
尾递归
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
函数的作用域
-
python 提供了内存管理,函数内的变量只在函数运行时才被创建,在函数运行之前会结束后根本不存在。在函数运行时会创建新的变量在函数中使用,当函数完成的时候他们会被删除。
-
函数运行时,函数之外的变量会被搁置,只有函数内部的名字会被用到。程序中使用变量的部分称为这个变量的作用域。
-
外部不能访问函数内部变量
-
函数内部能够访问外部变量
-
函数内部和函数外部变量名可以相同,但需要注意访问优先级
-
函数内部不能修改外部变量,强行修改需要加
global 外部变量 = 新值
局部变量
只在函数内部存在
全局变量
有更大作用域的变量,更大指程序的主部分。
可以在函数内部打印全局变量,但是当你试图改变它时,会创建一个新的局部变量
def Tax(price,rate): # price,rate,total是局部变量
total = price + price * rate
return total
Mytotal = Tax(60.6) # Mytotal 是全局变量
print(Mytotal)
Python 不会建立名为 Myprice的局部变量,而是会使用名为 Myprice的全局变量。
强制为全局变量
- global 关键字
def Tax(price, rate):
global Myprice
nonlocal 关键字
如果遇到函数内部局部变量和全局变量同名的情况,那么在函数内部,局部变量会覆盖全局变量,比如下面这种:
MIN_VALUE = 1
MAX_VALUE = 10
def validation_check(value):
MIN_VALUE = 3
...
在函数 validation_check() 内部,我们定义了和全局变量同名的局部变量 MIN_VALUE,那么,MIN_VALUE 在函数内部的值,就应该是 3 而不是 1 了。
类似的,对于嵌套函数来说,内部函数可以访问外部函数定义的变量,但是无法修改,若要修改,必须加上 nonlocal 这个关键字:
def outer():
x = "local"
def inner():
nonlocal x # nonlocal关键字表示这里的x就是外部函数outer定义的变量x
x = 'nonlocal'
print("inner:", x)
inner()
print("outer:", x)
outer()
# 输出
inner: nonlocal
outer: nonlocal
本文来自博客园,作者:是小鱼呀,转载请注明原文链接:https://www.cnblogs.com/sophia12138/p/17015130.html