函数
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
为什么要用函数
1、代码的组织结构不清晰,可读性差
2、遇到重复的功能只能重复编写实现代码,代码冗余 3、功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大函数的分类
主要分两类,内置函数和自定义函数
- 内置函数 python解释器事先为我们内置好的函数以便实现简单功能。拿来就用,无需事先定义。比如len(), sum(),type()
- 自定义函数 内置的函数很有限,大多数的时候需要我们根据自己的需求,进行自定义函数来实现某种功能,在以后用的时候,直接调用。
例如
def calc(x,y): res=x*y # print(res) return resc=calc(5,8)print(c)
定义函数
一、 如何定义函数
语法:def 函数名(参数1,参数2...): '''注释''' 函数体 return 返回值
二、函数的使用原则
先定义,在调用
def foo(): print('from foo') bar()foo()>>>NameError: name 'bar' is not defineddef foo(): print('from foo') bar()def bar(): print('from bar')foo()>>>from foo>>>from bar我们在使用函数时,一定要明确区分定义阶段和调用阶段
函数在定义阶段,只检查语法,逻辑错误只有在调用阶段才知道。
##### 定义函数的三种形式
- 无参: 仅仅是执行一些操作,比如用户交互,打印
- 有参:函数体依赖于外部传入的参数,比如求最大值最小值。
- 空函数: 编程初期,仅仅是为了设计代码结构,函数体通常为pass
无参def msg(): print('this is bruce')msg()支付系统def msg(): print(tag1()*35) print(tag2()*10,'welcom to ATM',tag2()*10) print(tag1()*35)def tag1(): return "*"def tag2(): return "="def pay(): print('from pay')def check(): print('from check')def transfer(): print('from transfer')def likai(): return quit()while True: def run(): print(''' 1 支付 2 检查 3 交易 4 退出 ''') choice=input('please select one>>> ').strip() if choice=='1': pay() elif choice=='2': check() elif choice=='3': transfer() elif choice=='4': likai() else: print('please retry,{} times left' .format(retry)) run()有参def max(x,y): if x>y: return x else: return yres=max(5,8)print(res)>>>8def tag(tag,n): print(tag*n)def msg(): print('hello brother')tag("*",15)3msg()tag("*",15)>>>***************hello brother***************
调用函数
如上例所示,函数是通过函数名加括号调用,
其实,函数调用有三种形式
- 语句形式: msg()
- 表达式形式:3*len()
- 当做另外一个函数的参数
函数返回值
return 是函数结束的标志,函数内可以有多个return,但是只要执行一个,函数就结束。而且把return的值当做本次调用的结果返回。
返回值没有类型限制,可以是任意类型。
def max2(x,y): if x>y: return [1,2,3,4] else: return {'a':8,'b':4,'c':0},'hello,workd',18,['a',1,{'t':1}]print(max2(1,2))>>>({'a': 8, 'b': 4, 'c': 0}, 'hello,workd', 18, ['a', 1, {'t': 1}])
一般手工指定return,如没有指定,则返回None
return 1个值-->返回1个值
return逗号分隔多个值,返回值是元组,见上例
({'a': 8, 'b': 4, 'c': 0}, 'hello,workd', 18, ['a', 1, {'t': 1}])
什么时候该有返回值?
调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值
通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果
什么时候不需要有返回值?
调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值
通常无参函数不需要有返回值
函数的参数
分为两大类
形参
变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量实参
可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
位置形参:定义函数的时候,按照从左到右的顺序依次定义的形参,叫位置形参,位置形参必须被传值,多一个不行少一个也不行
位置实参: 在调用函数时,按照从左到右的顺序依次传入的值,称为位置实参,位置实参与形参一一对应
def foo(x,y,z): print(x,y,z) foo(1,2,3) foo(1,2) foo(1,2,3,4)
默认形参: 在函数定义阶段,就已经被赋值的参数,称为默认形参,比如contry='CN'。默认参数的值应该设置成不可变类型(字符串,数字,元组)
在调用阶段可以不赋值而采用默认值。如果赋值则采用新值。默认参数只有在定义阶段被赋值一次就固定死了,定义之后的改变不受影响。
``` def ailen (x,y,z=10): return x,y,z
print(ailen(1,2,3))
(1, 2, 3)
def ailen (x,y,z=10):
return x,y,zprint(ailen(1,2))
(1, 2, 10)
m=10
def foo(x,y=m): print(x) print(y) m=111 #不受影响 foo(1)1
10
4. 关键字实参: 在函数调用阶段,采用key=value形式定义的实参,称为关键字实参。可以完全打乱顺序,相当于指名道姓的为形参传值。 位置实参可以和关键字实参混合使用,一定要放到位置参数的后面,且同一形参只能被赋值一次。
def ailen (x,y,z):
print(x,y) ailen(1,2,3)ailen(1,2,3,4) #报错 没有一一对应
ailen(1,y=4,z=2)
ailen(1,y=4,x=2) #报错,x被赋值两次。学生注册信息
def stu_register(name,age,course,contry='CN'):
print('注册信息') print('姓名',name) print('年龄',age) print('国籍',contry) print('课程',course) stu_register('bruce',22,'python') stu_register('peter',32,'CN','linux') stu_register('elaine', 18,'CN','English')注册信息
姓名 bruce 年龄 22 国籍 CN 课程 python 注册信息 姓名 peter 年龄 32 国籍 linux 课程 CN 注册信息 姓名 elaine 年龄 18 国籍 English 课程 CN
##### 非固定参数若你的函数在调用时不确定用户想传入多少个参数,就可以使用非固定实参,实参无非两种形式,1. 位置实参,2. 关键字实参, 所以对应的,形参也必须有两种解决方案,专门用于接收溢出的位置实参和关键字实参。
形参中用 * 接收位置实参,存成元组形式,然后赋值给后面的变量。
def foo(x,y,*z):
print(x,y,z) foo(1,2,3,4,5)1 2 (3, 4, 5)
实参中用 * 传递值给形参
def func(x,y,z): print(x,y,z) func(1,2,(3, 4, 5))
func(1,2,[3, 4, 5]) func(1,2,'345')1 2 (3, 4, 5)
1 2 (3, 4, 5) 1 2 ('3', '4', '5')
形参中用 ** 接收关键字实参,存成字典形式,然后赋值给后面的变量
def foo(x,y,**z):
print(x,y,z)foo(1,2,z=4,a=5)
1 2 {'z': 4, 'a': 5}
实参中用 ** 传递值给形参
def func(x,y,z): print(x,y,z) func(1,2,{'z':3,'a':4,'b':5})
1 2 {'z': 3, 'a': 4, 'b': 5}
更多的时候,按照python界俗称的约定,用```*args``` 代表```*z```,用```**kwargs```代表```**z```
def bruce(*args,**kwargs):
print(args) print(kwargs) bruce(1,2,3, x=100,y=200)(1, 2, 3)
{'x': 100, 'y': 200}
##### 练习题1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作
def modify_file(filename,old,new):
import os with open(filename,'r',encoding='utf-8') as read_f, open('.bak','w',encoding='utf-8') as write_f: for line in read_f: if old in line: line=line.replace(old,new) write_f.write(line)os.remove(filename)os.renames('.bak',filename)
modify_file('access.txt', 'a','1')
2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数
def check_str(msg):
dic={ 'digit':0, 'letter':0, 'space':0, 'other':0 } for s in msg: if s.isdigit(): dic['digit']+=1 elif s.isalpha(): dic['letter']+=1 elif s.isspace(): dic['space']+=1 else: dic['other']+=1 print(dic)check_str('jaldsjfelsajdlf32 12123 zd 9')
3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。
def checklen(msg):
if len(msg)>5: print('YES') else: print('NO')checklen([1,2,3,4,5])
4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
def len_check(msg):
if len(msg)>2: return (msg[0:2])print(len_check(['a,b,c,d,e','b','c']))
5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。
def in_check(msg):
return msg[::2] print(in_check([1,2,3,4,5,6]))```