python - 函数
函数的概念
什么是函数呢?可以说是一堆代码的集合,更确切的是能解决一个问题的代码集合,那为什么需要函数 呢?在写代码,码程序的时候,时常遇到一些重复性多的又有些许变动的要求,就需要函数了。比如在欢迎屏上打印来屏的名字,加上一成不变的祝福语句,那就再适合不过了。如:
guest = ['王老五','obama','李四','张三']
str1 = '\n欢迎茬临...'
str2 = '\n祝您事事顺心,万事如意!'
for guester in guest:
print(guester,str1,str2)
王老五
欢迎茬临...
祝您事事顺心,万事如意!
obama
欢迎茬临...
祝您事事顺心,万事如意!
李四
欢迎茬临...
祝您事事顺心,万事如意!
张三
欢迎茬临...
祝您事事顺心,万事如意!
如果每次我们都要敲一遍,是有点复杂,我们把上面的需求做成函数来调用,下次只需要客户明单即可。
def greeting(): #定义函数
for guester in guest:
print(guester)
print(str1,str2)
greeting() #调用函数
王老五
欢迎茬临...
祝您事事顺心,万事如意!
obama
欢迎茬临...
祝您事事顺心,万事如意!
李四
欢迎茬临...
祝您事事顺心,万事如意!
张三
欢迎茬临...
祝您事事顺心,万事如意!
函数的创建
函数体:
def funtionName(参数1,参数2,...,):
<函数体>
<return>
定义函数
函数 的定义使用def ,后面跟funtionName,也即是函数名字(首字母小写),函数名字尽量使用英文,不得使用下列:
- 数字开头
- 名称中有特殊符号
- 和python内置函数重名
取名时尽量做到见名知义,采用驼峰命名法。
def printMax():
def account_append():
函数的说明
在函数给人使用时,简短的函数名字不足以让别人了解其中的奥秘,为此,可以在python中,添加长字符串说明函数的功能与使用方法。
def printMax():
```
提供一个迭代对象,遍历后输出最大值
```
函数的返回值
函数在没有使用return 返回数据时,默认返回值是None.
type(lookType)
<class 'NoneType'>
函数的参数
位置参数
在函数定义或调用时,默认使用的是位置参数。如:
#定义一个函数,默认有a,b二个参数,a是需要比较大小的列表,b是布尔值,为真时比大,为假时比小。
lista = [1,2,3,4,5,5,5,6,9,0]
def printMax(a,b):
```
这是一个比较大小的函数,需要提供二个参数,a为列表,b为布尔值,为真
比较大,为假时比较小。
```
if b:
print(max(a))
else:
print(min(a))
printMax(lista,True) #比大
9
printMax(lista,False) #比小
0
在调用时,需要密切留意参数的位置,位置错误会引发函数崩溃。
Traceback (most recent call last):
File "<pyshell#136>", line 1, in <module>
printMax(True,lista)
File "<pyshell#133>", line 3, in printMax
print(max(a))
TypeError: 'bool' object is not iterable
如果我们定义一个函数,参数过多时,可以在函数调用时采用关键字参数。
关键字参数
为解决上述调用函数需对位置函数密切留意的问题,python支持在函数调用时采用关键字参数。
printMax(b = False,a = lista)
0
printMax(b = True,a = lista)
9
这样,就可以不必太过留意参数之间位置的问题,但是在调用时,位置参数必须在最左则,不然会调用失败。
printMax(b = False,lista)
SyntaxError: positional argument follows keyword argument
大家想一下,如果我这样写会怎么样:
printMax(b = True,(19,22,33,44,55,66,1))
printMax([19,22,33,44,55,66,1],b = True)
默认值参数
在函数定义时,我们对有一项是可有可无的需求时,可以使用参数的默认值。在未录入时采用默认值,有录入时采用录入值。
def printPersonInfo(name,age,phone=''):
print(name,age,phone)
printPersonInfo('h',18)
h 18
printPersonInfo('h',18,13718271890)
h 18
收集参数
- args
在我们不知道需要多少个参数时,如需要太多参数,定义太费手时,可以使用args,底层args是用tuple。
def printMax1(*args):
print(*args)
return max(*args)
printMax1(1,2,3,4,5,1,9,0)
1 2 3 4 5 1 9 0
9
- **args
底层是用字典保存参数,
def printPerson(index,**args):
print('args的信息是%s' % args)
for each in args.items(): #打印字典的k,v值,以tuple方式保存。
print(each)
printPerson(1,a=2,c=3,csdn='www.csdn.ort')
args的信息是{'a': 2, 'c': 3, 'csdn': 'www.csdn.ort'}
('a', 2)
('c', 3)
('csdn', 'www.csdn.ort')
混合参数
记住一个原则,位置参数必须最左,字典收集参数必须最右
位置参数->默认参数->元组收集参数->字典收集参数。
def boring(name,sex='man',*aspect,**info):
str1 = ''
str2 = ''
for i in aspect:
str1 += i
for each in info.items():
str2 += each[0]+'是'+str(each[1])
print('%s的性别是%s\n,respt是%s\n,info是%s\n'%(name,sex,str1,str2))
boring('csdn','women','black','cool','sweet','love',salary=10000,cars='bmw')
csdn的性别是women
,respt是blackcoolsweetlove
,info是salary是10000cars是bmw
这里的sex在收集参数之前,所以必须使用关键字指定,否则会被 收集哦
参数小知识
TIPS:
在一些函数定义里面,我们可以看到:
- 必须使用关键字参数
funA(100,200)
100 200
funA(100,b=200)
100 200
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
funA(b=200,a=100)
TypeError: funA() got some positional-only arguments passed as keyword arguments: 'a'
‘/’之前的参数必须使用位置参数,调用时不得使用关键字参数
- 必须使用关键字参数
与上相反的是,必须要指定关键字参数也有其定义方式:
def funB(a,*,b,c):
print(a,b,c)
funB(100,200,300)
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
funB(100,200,300)
TypeError: funB() takes 1 positional argument but 3 were given
funB(100,b=200,300)
SyntaxError: positional argument follows keyword argument
funB(100,200,c=300)
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
funB(100,200,c=300)
TypeError: funB() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given
funB(100,b=200,c=300)
100 200 300
funB(a=1,b=200,c=300)
1 200 300
函数的调用方式
普通调用方式
在定义好一个函数后,可以在控制台,直接输入函数名进行调用。也可以把函数名赋值给一个变量,如:
def funAdd(a,b): #定义一个函数,把里面的二个参数进行相加
return a+b #返回两个参数相加的结果
funAdd(3,5) #普通调用方式
8
a = funAdd #把funAdd赋值给a变量,深层次是把funAdd的id给了a,如果funAdd后面跟了小括号,则是把funAdd的返回值赋值给了变量a。
id(funAdd) #查看函数的id
2658843228720
id(a) #查看变量a的id.
2658843228720
a is funAdd #变量a和函数funadd是否是同一对象。
True
a(3,4) #正常调用。
7
将函数作为参数调用
将函数作为参数传送
def time_master(func): #time_master函数的参数是func哦。。
start = time.time()
print('time开始计时了哦~~')
func() #运行程序的调用
end = time.time()
print('time计时结束了哦~~')
print('func使用了%d 秒'%(end-start)) #输出相关信息。
time_master(funC) #调用master,将funC函数做为参数进行传递,这里的funC可不能带()哦,不然就变成返回值了。
time开始计时了哦~~
func运行ok
time计时结束了哦~~
func使用了2 秒
tips:想一想,为啥func()不能有相应的参数呢,如果有参怎么定义函数呢?
这里等下会讲到,涉及到闭包,工厂函数呢…
函数嵌套函数
说到嵌套,应该不会陌生,循环有嵌套,函数也有嵌套,这里我浅显的说一些个人的理解,现在的术语应该是套娃,一层套一层,差不多这个意思。
def outer():
print('这是外层函数')
def inner():
print('这是内层函数')
inner()
outer()
这是外层函数
这是内层函数
a = outer
a()
这是外层函数
这是内层函数
闭包函数
闭包就是外部函数中定义一个内部函数,内部函数引用外部函数中的变量,外部函数的返回值是内部函数;
闭包函数和嵌套函数类似有以下基本特征。
- 首先它是一个嵌套函数,有外层函数,内部函数。
- 内部函数调用外部函数的变量。
- 外部函数调用时需要将内部函数返回。
示例:
设计一个有记忆功能的列表,每次增加一个元素,就会列出里面所有的元素和。
def outer(): #定义一个外层函数,特征一
lista = [] #定义一个内部函数需要用到的变量;特征二
def inner(num): #定义一个内部函数
lista.append(num)
print('列表现有%d个元素,它们的和为:%d'%(len(lista),sum(lista)))
return inner #将内层函数作为返回值返回给外层函数;特征三
summary = outer()
summary(4)
列表现有1个元素,它们的和为:4
summary(6)
列表现有2个元素,它们的和为:10
summary(20)
列表现有3个元素,它们的和为:30
工厂函数
这也是闭包的一种,可以在外部函数中定义程序的轮廓,内部函数作为生产出来的模具使用,比如,自定义扩展,m的n次幂。工厂函数有闭包的一切特征。
def base(n): #定义一个外层函数,n即是内层函数需要用到的变量;
def exp(m): #定义一个内层函数
return m ** n #返回m的n次幂。
return exp #将内层函数作为返回值返回给外部函数;
squer = base(3) #3次幂
cube = base(2) #2次幂
squer(2)
8
squer(3)
27
cube(2)
4
cube(3)
9
修饰函数
语法糖中的一种,也是闭包函数的一种。和当函数作参数传递有一点不同。
def cost_time(f): #定义一个外层函数,将f函数作为参数传入内层函数中去。
def inner(*args,**kwargs): #定义一个内层函数,设置参数为可变收集参数,这样可以与外层f函数的调用保持一致。
print('开始计时..')
start = time.time()
f(*args,**kwargs)
end = time.time()
print('结束计时...\n耗费时间为:%.4f'%(end - start))
return inner
mycost = cost_time(funa)
mycost(1,2,3,4,5,6,'Fishc',a=3,b=9,c=33,d='ok')
开始计时..
1
2
3
4
5
6
Fishc
('a', 3)
('b', 9)
('c', 33)
('d', 'ok')
结束计时...
耗费时间为:2.1551
除此方法外,也可使用另一个方式,修饰符的方式,在定义需要修饰的函数上方,采用‘@’加修饰函数。
@cost_time
def syjik(a,b,/,d):
print(a,b,'必须为位置参数传递进来,d可为关键字参数也可为位置参数传递.',d)
syjik('skj','ok',111)
开始计时..
skj ok 必须为位置参数传递进来,d可为关键字参数也可为位置参数传递. 111
结束计时...
耗费时间为:0.0348
syjik('skj','ok',d=111)
开始计时..
skj ok 必须为位置参数传递进来,d可为关键字参数也可为位置参数传递. 111
结束计时...
耗费时间为:0.0284
syjik('skj',b='ok',d=111)
开始计时..
Traceback (most recent call last):
File "<pyshell#159>", line 1, in <module>
syjik('skj',b='ok',d=111)
File "<pyshell#150>", line 5, in inner
f(*args,**kwargs)
TypeError: syjik() got some positional-only arguments passed as keyword arguments: 'b'
lambda函数
lambda也是一句话函数,在map,filter中大有用处,示例:
map
mapped = map(lambda x: x *2,[1,2,3,4,5,6,7])
mapped.__next__()
2
next(mapped)
4
list(mapped)
[6, 8, 10, 12, 14]
filter
filed = filter(lambda x: x>7,map(lambda x: x *2,[1,2,3,4,5,6,7]))
filed.__next__()
8
next(filed)
10
tuple(filed)
(12, 14)
other
mapped1 = lambda x,y:y**x
mapped1(2,4)
16
mapped2 = lambda x:lambda y :y**x
mapped2(2)(3)
9