函数定义:
1 def say_hello(): 2 # 该块属于这一函数 3 print('hello world') 4 # 函数结束 5 say_hello() # 调用函数 6 say_hello() # 再次调用函数
5.1 return关键字的用法
1,在函数中,遇到return结束函数。
2,将值返回给函数的调用者。
5.1.1 没有返回值:
#函数定义 def mylen(): """计算s1的长度""" s1 = "hello world" length = 0 for i in s1: length = length+1 print(length) #函数调用 str_len = mylen() #11 #因为没有返回值,此时的str_len为None print('str_len : %s'% str_len)
5.1.2 return可用来结束整个函数 (看着好像是函数里面有return的时候,调用函数的时候才需要打印的)
如果 return 语句没有搭配任何一个值则代表着 返回 None 。 None 在 Python 中一个特殊的类型,代表着虚无。
举个例子, 它用于指示一个变量没有值,如果有值则它的值便是 None(虚无) 。
每一个函数都在其末尾隐含了一句 return None ,除非你写了你自己的 return 语句。
这里我们要说一下return的其他用法,就是一旦遇到return,结束整个函数。
def ret_demo(): print(111) return #注意,因为有return,这里只会返回‘111’,不会在进行下面的运算 print(222) ret = ret_demo() print(ret)
5.1.3返回一个值(该值是什么,直接返回给函数的调用者)
#函数定义 def mylen(): """计算s1的长度""" s1 = "hello world" length = 0 for i in s1: length = length+1 # 只会返回’11‘ return length #函数调用 str_len = mylen() print('str_len : %s'%str_len)
5.1.4 返回多个值 (将多个值返回到一个元祖里面,返回给函数的调用者)
def ret_demo1(): '''返回多个值''' return 1,2,3,4 # 记住return后面多个值不需要括号的,另外返回的值都是元祖,而非字符串
def ret_demo2(): '''返回多个任意类型的值''' return 1,['a','b'],3,4 ret1 = ret_demo1() print(ret1) ret2 = ret_demo2() print(ret2)
5.1.5 多个返回值的接收:
def ret_demo2(): return 1,['a','b'],3,4 #返回多个值,用一个变量接收
ret2 = ret_demo2() print(ret2) #用多个值接收返回值:返回几个值,就用几个变量接收
a,b,c,d = ret_demo2() print(a,b,c,d) ---(1, ['a', 'b'], 3, 4) #返回的是元祖类型 ---1 ['a', 'b'] 3 4
5.2 函数参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.按照位置传参 def mymax(x,y): #此时x=10,y=20 the_max = x if x > y else y return the_max ma = mymax(10,20) print(ma) 2.按照关键字传参(函数调用过程中通过参数名制定需要赋值的参数) def mymax(x,y): #此时x = 20,y = 10 print(x,y) the_max = x if x > y else y return the_max # 对于一个形参只能赋值一次 ma = mymax(y = 10,x = 20) print(ma) 3.位置,关键字形式混着用 def mymax(x,y): #此时x = 10,y = 20 print(x,y) the_max = x if x > y else y return the_max ma = mymax(10,y = 20) # 位置参数必须在关键字参数的前面 print(ma)
站在形参角度:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def lens(x): # x即形参 count = 0 for j in x: count += 1 return count x = 'dwdfefvwf' print(len(x)) # 此时传入的x为实际参数,相当于 'dwdfefvwf'
将变化较小的值设为默认参数:
def stu_info(name,sex = "male"): """打印学生信息函数,由于班中大部分学生都是男生, 所以设置默认参数sex的默认值为'male' """ print(name,sex) # 这结果有意思 stu_info('alex') stu_info('eva','female') ---alex male ---eva female
def defult_param(a,l = []): l.append(a) print(l) # 这里的默认参数可变,有点像动态传递,a得到结果后又传递到了列表里面 defult_param('alex') defult_param('egon') ---['alex'] ---['alex', 'egon']
通过在函数定义时附加一个赋值运算符( = )来为参数指定默认参数值 默认参数应该是常数,即不可变 def say(message, times=1): # 只有那些位于参数列表末尾的参数才能被赋予默认参数值 print(message * times) say('Hello') say('World', 5) ---Hello ---WorldWorldWorldWorldWorld
关键字传参:
def func(a, b=5, c=10): print('a is', a, 'and b is', b, 'and c is', c) func(3, 7) func(25, c=24) func(c=50, a=100) ---a is 3 and b is 7 and c is 10 ---a is 25 and b is 5 and c is 24 ---a is 100 and b is 5 and c is 50
5.3 可变参数(收集参数)
*args在行形参中对应关系:
位置参数,*args, 默认参数
def func(a,b,c,*args,d = 2): print(a,b,c,args,d) func('s','w','d',5,8,21,3,15,'f') ---s w d (5, 8, 21, 3, 15, 'f') 2 # d = 2没有被覆盖,能打印出来 def func(a,b,c,d = 2,*args): print(a,b,c,args,d) func('s','w','d',5,8,21,3,15,'f') ---s w d (8, 21, 3, 15, 'f') 5 # d现在是5,打印结果在最后 如果d = 2放在形参前面,则会报错
**kwargs在形参中对应关系:
最终顺序:位置参数,*args,默认参数,**kwargs
def func(a,b,c,d,*args,e='男',**kwargs): print(a,b,c,args,e,kwargs) # 这里没有打印d值 func(1,2,3,4,5,6,7,v=3,m=7,h=9,e='女') #d对应4 ---1 2 3 (5, 6, 7) 女 {'v': 3, 'm': 7, 'h': 9}
关于*args以及**kwargs的魔法应用
def func(*args): print(args) l1 = [1,2,30] l2 = [1,2,33,21,45,66] tu = (1,2,3) func(1,2,30,1,2,33,'das',2,5,66) ---(1, 2, 30, 1, 2, 33, 'das', 2, 5, 66) func(*'qweqrfdsaf') ---('q', 'w', 'e', 'q', 'r', 'f', 'd', 's', 'a', 'f') func(*{'name':'alex',"age":12}) ---('name', 'age') func(*l1,*l2) ---(1, 2, 30, 1, 2, 33, 21, 45, 66)
def func(**kwargs): print(kwargs) dic1 = {'name1':'alex','age1':46} dic2 = {'name':'老男孩','age':56} func(**dic1,**dic2) ---{'name1': 'alex', 'age1': 46, 'name': '老男孩', 'age': 56}
从上面例子可以看出:
针对*,打散(list,tuple,str,dict(键),将元素一一添加到args
针对**,打散所有字典,并将所有键值对放到一个kwargs
def total(a=5, *numbers, **phonebook): print('a', a) #遍历元组中的所有项目 for single_item in numbers: print('single_item', single_item) #遍历字典中的所有项目 for first_part, second_part in phonebook.items(): print(first_part,second_part) print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560)) ---a 10 ---single_item 1 ---single_item 2 ---single_item 3 ---Inge 1560 ---John 2231 ---Jack 1123 ---None
如果有搜集参数,后面还有其他参数,则建议使用默认参数:
def test(*params, exp = 8): print ("参数长度是:", len(params),exp) print ("第二个参数是:",params[1]) test(1,"cedf",74,415,6) ---参数长度是: 5 8 ---第二个参数是: cedf
5.4局部变量与全局变量
# 在全局是无法查看全局的,但是通过局部可以查看全局
max=1 def f1(): max=2 def f2(): max=3 print(max) f2() f1() print(max)
#在函数局部作用域内 name = 'wusir' def func(): name = 'alex' print(globals()) print(locals()) #{'name': 'alex'} func() #输出结果: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002397E843FD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/python10/day10/homework.py', '__cached__': None, 'name': 'wusir', 'func': <function func at 0x000002397CA62E18>} {'name': 'alex'}
def func(): global a a = 2 #用以声明a是一个全局变量 print(a) func() #2 print(a) #2 #从这个结果可以看出来a现在属于全局变量 #输出结果 2 2
对可变数据类型(list,dict,set)可以直接引用不用通过global:
li = [1,2,3] dic = {'a':'b'} def change(): li.append('a') dic['q'] = 'g' print(dic) #{'a': 'b', 'q': 'g'} print(li) #[1, 2, 3, 'a'] change() print(li) #[1, 2, 3, 'a'] print(dic) #{'a': 'b', 'q': 'g'}
def add_b(): b = 42 def do_global(): b = 10 print(b) #10 def dd_nonlocal(): nonlocal b b = b + 20 print(b) #30 dd_nonlocal() print(b) #30 do_global() print(b) #42 add_b() #输出结果 10 30 30 42
函数的嵌套使用:
def fun1(): print('fun1()正在被调用') def fun2(): #注意缩进 print('fun2()正在被调用') fun2() fun1() ---fun1()正在被调用 fun2()正在被调用 def fun1(): print(111) def fun2(): print(222) fun1() fun2() #输出结果 222 111
print(111) #执行顺序--1 def fun2(): print(222) #执行顺序--3 def fun3(): print(666) #执行顺序--5 print(444) #执行顺序--4 fun3() print(888) #执行顺序--6 print(333) #执行顺序--2 fun2() print(555) #执行顺序--7 #函数看着有点绕,仔细分析缩进及自上而下的调用过程 #输出结果 111 333 222 444 666 888 555
相关作业:
2、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。
def key(s): a = s[1::2] return a print(key([1, 5, 8, 8, 9, 11, 11])) print(key(('d', 'a', 'e', 'e')))
3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。
def stuff(x): return '大于5' if len(x) > 5 else '小于5' print(stuff(('w', 'd', 'w', 'l' 'e'))) print(stuff([15,54,5,3,15,35])) print(stuff('dewfwegw'))
4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
def stuff(x): a = x[:2] if len(x) > 2 else x return a # 和上面这一步可以合并 print(stuff([15,41,56,4,56,4,1,5])) def stuff(x): return x[:2] print(stuff([15,41,56,4,56,4,1,5]))
5、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数,并返回结果。
# 一般遇到计算当中某个元素出现次数,下面的编程思想可得记住了 def stuff(x): num = 0 alpha = 0 space = 0 other = 0 for i in x: if i.isdigit(): num += 1 elif i.isalpha(): alpha += 1 elif i.isspace(): space += 1 else: other += 1 print('num:{}个 alpha:{}个 space:{}个 other:{}个'. format(num, alpha, space, other)) stuff('dwwf few#@%6 564def 156we') def func(stuff): a = {'num': 0, 'alpha': 0, 'space': 0, 'other': 0} for element in stuff: if element.isdigit(): a['num'] += 1 elif element.isalpha(): a['alpha'] += 1 elif element.isspace(): a['space'] += 1 else: a['other'] += 1 return '数字%d,字母%d,空格%d,其他%d' % (a['num'], a['alpha'], a['space'], a['other']) print(func('fdsafd 1232432@#$%^fdf123 哈佛撒旦'))
7、写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
dic = {"k1": "v1v1", "k2": [11,22,33,44]}
PS:字典中的value只能是字符串或列表
def dics(dic): for k in dic: if len(dic[k]) > 2: dic[k] = dic[k][:2] else: dic[k] = dic[k] return dic # 注意这个缩进位置 print(dics({"k1": "v1v1", "k2": [11,22,33,44]})) def dics(dic): for k in dic: dic[k] = dic[k][:2] return dic print(dics({"k1": "v1v1", "k2": [11,22,33,44]}))
8、写函数,接收两个数字参数,返回比较大的那个数字。
def max_num(a, b): return a if a > b else b print(max_num(3, 5))
9、写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作(进阶)。
# 这个对原文件全部给清空了,然后输入新内容了。 # 如果题目要求只是追加的话就不好了.那么需要在创建一个文件 from os import rename def load_in(content, file_name): with open('a.txt', mode='w', encoding='gbk') as f: f.write(content) rename('a.txt', file_name) # 这个缩进注意啦,麻痹的研究了好久原来这里错了 load_in('吃葡萄不吐葡萄皮', 'bb.txt')
10、写一个函数完成三次登陆功能,再写一个函数完成注册功能(进阶)
# 用户注册 li = [] def register(): username = input('请输入你的注册名:').strip() with open('register_msg.txt', encoding='gbk') as f: for line in f: names = line.strip().split() li.append(names[0]) if username in li: print('你所注册的用户名已存在,请重新输入') return register() else: password = input('请输入你的注册密码:').strip() with open('register_msg.txt', encoding='gbk', mode='a') as f1: f1.write(' {} {}'.format(username, password)) print('注册成功') register() # 用户登陆 def func(): # 用户选择登陆还是注册函数 choice = input('选择登陆/0还是注册/1:').strip() if choice == '1': register() # 执行注册函数 elif choice == '0': # 执行登陆 times = 0 while times < 3: times += 1 def fun1(): # 登陆函数 username = input('请输入你的用户名:').strip() password = input('请输入密码:').strip() with open('register_msg.txt', encoding='gbk') as f: for line in f: # 打开文件,读取每行 li = line.strip().split() # 对每行切割,得到列表 if username == li[0] and password == li[1]: # 判断用户名是否在文件内 print('登陆成功') while True: # 登陆成功后,继续选择登陆注册或者退出 choice = input('请选择登陆还是注册/1还是退出/2:').strip() if choice == '1': return func() # 返回,继续执行上面函数 elif choice == '2': exit() else: print('你输入的有误,请重新输入') else: print('你的输入有误') fun1() # 执行fun1登陆函数 if times == 3: print('你输入的次数已用完') exit() else: print('你输入的包含非法字符,重新输入') func() # 调用登陆or注册函数