七、函数
(1)函数的定义
以def 为开头,后接函数名和圆括号冒号,return 函数结束
(2)函数的调用
def goodday(arg):
return arg**2
print(goodday(3)) #9
(3)函数文档
程序定义过程中传递过来的是形参(如:a)实际的是实参(3)
(4)函数参数
- 位置参数
def functionname(arg1):
"函数_文档字符串"
function_suite
return [expression]
arg1就是位置参数,固定
2. 默认参数
def functionname(arg1, arg2=v):
"函数_文档字符串"
function_suite
return [expression]
arg2=v就是默认参数,当没给出固定值的时候,v就是默认值默认参数要放在位置参数后边
def goodday(name,age=13):
print('name:{0},age:{1}'.format(name,age))
goodday('发得少') # name:发得少,age:13
goodday( '干哈',84) # name:干哈,age:84
- 可变参数
就是传入的参数的个数是可变的
*args-可变参数,自动组成元组,加了 星号的变量名会存放所有的未知变量参数
可变参数允许传入零个到任意个参数,它们在函数调用时自动组装为一个元组 (tuple)
def goodday(arg,*args):
print(arg)
for i in args:
print(i)
goodday(130) # 130
goodday('sdf') # sdf
goodday('fsds',['fsdfs',2348790],543)
# fsds ['fsdfs', 2348790] 543
def qhfuji(a,*b):
print(a)
print(b)
qhfuji(3432) # 3432 ()
qhfuji(45234,'sdgj',('fsd',6425,[674,'dfg']))
# 45234 ('sdgj', ('fsd', 6425, [674, 'dfg']))
- 关键字参数
def functionname(arg1, arg2=v, args, *kw):
"函数_文档字符串"
function_suite
return [expression]
**kw - 关键字参数,可以是从零个到任意个,自动组装成字典
def goodday(a,*b,**c):
print(a,b,c)
goodday(123) # 123 () {}
goodday(123,42)# 123 (42,) {}
goodday(312,65,465) # 312 (65, 465) {}
goodday(3123,67,468,46,'hf','hfg')
# 3123 (67, 468, 46, 'hf', 'hfg') {}
goodday(312,354,64,7,hf=3,gdf=3456,jh='fhg',gfd=534)
#312 (354, 64, 7) {'hf': 3, 'gdf': 3456, 'jh': 'fhg', 'gfd': 534}
关键词不能是表达式 --字符串(不能加引号),元组、列表、字典、集合不可以且不可以重复
可变参数允许传入零个到任意个参数,它们在函数调用时自动组装为一个元组 (tuple)
6. 命名关键字参数
def functionname(arg1, arg2=v, args, *, nkw, *kw):
"函数_文档字符串"
function_suite
return [expression]
*, nkw - 命名关键字参数,用户想要输入的关键字参数,定义方式是在nkw 前面加个分隔符 *
如果要限制关键字参数的名字,就可以用「命名关键字参数」
使用命名关键字参数时,要特别注意不能缺少参数名
def goodday(arg, *,nkw,**kwargs):
print(a,b,c)
goodday(123,nkw=213,fs=234,cq=342) # 123 213 {'fs': 234, 'cq': 342}
goodday(123,213,fds=452,fdads=32)
# TypeError: goodday() takes 1 positional argument but 2 were given
nkw=213中nkw=必须写
没有写参数名b,因此 213 被当成[位置参数],而原函数只有 1 个位置函数,现在调用了 2 个,因此程序会报错。
7. 参数组合
参数定义的顺序必须是:
位置参数、默认参数、可变参数和关键字参数
位置参数、默认参数、命名关键字参数和关键字参数
要注意定义可变参数和关键字参数的语法:
*args 是可变参数,args 接收的是一个 tuple
**kw 是关键字参数,kw 接收的是一个 dict
定义命名关键字参数不要忘了写分隔符 *,否则定义的是位置参数。
(5)函数的返回值
def back(a):
return a**3
print(back(3)) #27
def good():
print('goodday!')
good() #goodday!
def day():
print ['fsfs']
day()
# TypeError: 'builtin_function_or_method' object is not subscriptable
def et():
return ['shgd']
print(et()) #['shgd']
(6)变量作用域
- 定义在函数内部的变量拥有局部变量作用域,这个变量叫做局部变量
定义在函数外部的变量拥有全局变量作用域,这个变量叫做全局变量
局部变量只能在被声明的函数内部使用,全局变量可以在整个程序的范围内使用
def score(a,b):
c=a*0.7+b*0.3
return c
good=float(input('good=')) # good= 456
day=float(input('day=')) # day= 2165
print(score(good,day)) # 968.7
- 当内部作用域想要修改外部作用域的时候,要用到global和nonlocal关键字
num=123
def good():
global num
s=num**3
return s
print(good()) #1860867
- 内嵌
返回的是函数
def first():
print('第一个函数')
def second():
print('第二个函数')
second()
first() # 第一个函数 第二个函数
- 闭包
闭包是一种特殊的内嵌函数,如果一个内部函数里对外层非全局作用的变量进行引用,那么内部函数就被称作闭包,通过闭包可以访问外层非全局作用域的变量,这个作用域被称为闭包作用域
def funX(x):
def funY(y):
return x * y
return funY
i = funX(8)
print(type(i)) # <class 'function'>
print(i(5)) # 40
这个5相当于访问funY()函数
闭包的返回值通常是函数
def counter = [init]
def inc(): counter[0] += 1
def dec(): counter[0] -= 1
def get(): return counter[0]
def reset(): counter[0] = init
return inc, dec, get, reset
inc, dec, get, reset = make_counter(0)
inc()
inc()
inc()
print(get()) # 3
dec()
print(get()) # 2
reset()
print(get()) # 0
修改闭包作用域中的变量需要用到nonlocal关键字
def good():
a=13
def day():
nonlocal a
a=312
return a
day()
print(good()) #312
- 递归
一个函数在内部调用自己,这个函数就是递归函数
def good(a):
if a==1
return 1
return a*good(a-1)
print(good(3)) #6
斐波那契数列f(n)=f(n-1)+f(n-2), f(0)=0 f(1)=1
def recur_fibo(n):
if n <= 1:
return n
return recur_fibo(n - 1) + recur_fibo(n - 2)
lst = list()
for k in range(11):
lst.append(recur_fibo(k))
print(lst)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]