本篇博文详细讲述了函数的定义以及用法,以及一些典型的例子,对小白理解很有帮助,里面的内容和代码以及案例都是自己码的,程序一定要自己运行一下,理解弄懂就好了。
如有问题,欢迎大家批评指正!!!
这里写目录标题
1 函数
对于函数编程:
● 本质:将 N 行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码,并执行。
● 场景:
● 代码重复执行
● 代码量特别多,超过一屏,可以选择通过函数进行代码的分割
1.1 三元运算(三目运算)
三元函数是为了赋值的。前面的值 if 条件真 --> 前面的值 else 后面的值
if 条件 :
v = 前面
else:
v = 后面
v = 前面 if 条件 else 后面 # 一行就可以实现
1.2 函数的基本结构
# 函数的定义
def get_list_first_data():
v = [11,22,['alex',666]]
print(v[2])
# 函数的执行
get_list_first_data() #['alex', 666]
练习
# 假如,管理员、业务员、老板用的是同一个邮箱。发送邮件的例子,输入管理员、业务员、老板显示发送成功
def send_email():
print('邮件发送成功,假设有20行代码')
message = input('请输入角色:')
if message == '管理员':
send_email()
if message == '业务员':
send_email()
if message == '老板':
send_email()
2 参数
2.1 基本参数知识
● 任意个数
● 任意类型
def func(a1,a2,a3):
print(a1,a2,a3)
func(1,'alex',True)
● 补充:对于函数的默认值慎用可变类型。
# 如果要想给 value 设置默认是空列表
# 不推荐(坑)
def func(data,value=[])
pass
# 推荐
def func(data,value=None)
if not value:
value = []
举例:
def func(a,b=[]):
b.append(a)
return b
# 分开打印
l1 = func(1)
print(l1) # [1]
l2 = func(2,[11,22])
print(l2) # [11,22,2]
l3 = func(3)
print(l3) # [1,3]
# 默认是同一个地址,如果不传参数,那么 b = [] 会随着添加进来的元素而改变。现在的 l1 变成了 [1,3]
# 如果有参数传入,则用自己传入的参数
问题:
● def func(a,b=[]) 有什么陷阱?
b=[] 是可变类型,如果不传参数,默认是同一个地址。
● 看代码写结果
def func(a,b=[]):
b.append(a)
return b
l1 = func(1) # [1]
l2 = func(2,[11,22]) # [11,22,2]
l3 = func(3) # [1,3]
# 一起打印
print(l1,l2,l3) # [1,3] [11,22,2] [1,3]
def func(a,b=[]):
b.append(a)
return b
# 分开打印
l1 = func(1)
print(l1) # [1]
l2 = func(2,[11,22])
print(l2) # [11,22,2]
l3 = func(3)
print(l3) # [1,3]
● 看代码写结果
def func(a,b=[]):
b.append(a)
print(b)
func(1)
# [1]
func(2,[11,22])
# [11,22,2]
func(3)
# [1,3]
2.2 位置传参(调用函数,并传入参数)
def func(a1,a2):
print(a1,a2)
func(1,'alex') # 多一个或少一个都会报错
2.3 关键字传参 (位置可以打乱)
def func(a1,a2):
print(a1,a2)
func(a2=1,a1=99) # 顺序可以打乱
● 关键字传参数和位置传参数可以混合使用 (位置传参一定在关键字传参前面)
def func(a1,a2,a3):
print(a1,a2,a3)
func(1,2,a3=9)
func(1,a2=2,a3=9)
func(a1=1,2,9) # 报错
● 位置传参数在前 + 关键字传参数在后 = 参数总个数
● 先处理位置传参,再处理关键字传参
2.4 默认参数【定义】
def func(a1,a2=9): # 第二个位置的参数可传可不传,传--> 传的值,不传--> 默认9
pass
func(1,2) # 1 2
func(1,a2=18) # 1 18
func(a1=123,a2=999) # 123 999
func(12) # 12 9
例子:
def func(a1,a2,a3=9,a4=10):
print(a1,a2,a3,a4)
func(1,2) # 1 2 9 10
func(1,a2=18) # 1 18 9 10
func(a1=123,a2=999) # 123 999 9 10
func(1,2,a3=33,44) # 报错 前面若有关键字传参,后面一定也是关键字传参,位置传参一定是在关键字传参前面
func(1,a2=2,a3=33,a4=44) # 1 2 33 44
func(a1=1,a2=2,a3=33,a4=44) # 1 2 33 44
2.5 万能参数
1.*args 是多个变量组成的元组,输出的类型都是元组
def func(*a):
print(a)
print(type(a))
func(1) # (1,) <class 'tuple'>
func(1,2) # (1, 2) <class 'tuple'>
func((1,2,3,4,5)) # ((1, 2, 3, 4, 5),) <class 'tuple'>
func('alex',1,True,[11,22,33],(1,2)) # ('alex', 1, True, [11, 22, 33], (1, 2)) <class 'tuple'>
func(*(1,2,3,4,5)) # (1, 2, 3, 4, 5) <class 'tuple'>
func(*('alex',1,True,[11,22,33],(1,2))) # ('alex', 1, True, [11, 22, 33], (1, 2)) <class 'tuple'>
● *args 只支持位置传参,不支持关键字传参
● 可以接受任意个数的参数,并将参数转换成元组
● 调用函数有 *
def func(a1,*args):
print(a1,args)
func(1,2,3,4,5) # 1 (2, 3, 4, 5)
def func(a1,*args,a2):
print(a1,args,a2)
func(1,2,3,4,5) # 1 (2, 3, 4, 5) 只要a2 前面有args,a2永远拿不到值
def func(a1,*args,a2=10):
print(a1,args,a2)
func(1,2,3,4,5) # 1 (2, 3, 4, 5) 10
def func(a1=10,*args,a2=10):
print(a1,args,a2)
func(1,2,3,4,5) # 1 (2, 3, 4, 5) 10 1 把a1 = 10 覆盖了
● 调用函数无 *
def func(a1,a2=9):
pass
func(1,2) # 1 2
● 只能用位置传参
2.**kwargs 关键词传参:输出类型是字典
def func(**kwargs):
print(kwargs)
● **kwargs 只支持关键字传参
● 可以接受任意个数的关键字参数,并将参数转换成字典
● 调用函数有 **
func(**{'k1': 1, 'k2': 'alex'}) # {'k1': 1, 'k2': 'alex'}
● 调用函数无 **
func(k1=1,k2='alex') # {'k1': 1, 'k2': 'alex'}
3.综合应用
def func(*args,**kwargs):
print(args,kwargs)
func(1,2,(1,2),k1=1,k2='alex') # (1, 2, (1, 2)) {'k1': 1, 'k2': 'alex'}
3 函数的返回值
def func():
pass # 无返回值,默认None
def bar():
return 9 # 有返回值,返回9
3.1 return 用法
# 有返回+可修改数据
v = [11,22,33,44]
result = v.pop()
print(result)
print(v)
# 仅有返回值
v = 'alex'
result = v.split('l')
print(result) # ['a', 'ex'] 有返回值
v = {'k1':'v1','k2':'v2'}
result1 = v.get('k1') # v1
result2 = v.keys() # dict_keys(['k1', 'k2'])
print(result1,type(result2))
# 无返回值
v = [11,22,33,44]
v.append(99) # 无返回值
3.2 练习题
练习1 发送邮箱
# 邮箱 无返回值
def send_email(role,to):
template = '要给%s%s发送邮件'%(role,to,)
print(template)
message = input('请输入角色:')
if message == '管理员':
send_email('管理员','jdhsifs@qq.com') # 要给管理员jdhsifs@qq.com发送邮件
if message == '业务员':
send_email('业务员','4363657856@qq.com')
if message == '老板':
send_email('老板','jgdftgdr45s@qq.com')
val = send_email('管理员','jdhsifs@qq.com') # 调用返回值
print(val) # None 若有return,有返回值,否则,为None
# 邮箱 有返回值
def send_email(role,to):
template = '要给%s%s发送邮件'%(role,to,)
print(template)
return '结束'
message = input('请输入角色:')
if message == '管理员':
val = send_email('管理员','jdhsifs@qq.com') # 要给管理员jdhsifs@qq.com发送邮件 # 调用返回值
if message == '业务员':
val = send_email('业务员','4363657856@qq.com') # 调用返回值
if message == '老板':
val = send_email('老板','jgdftgdr45s@qq.com') # 调用返回值
print(val) # 结束 若有return,有返回值,否则,为None
练习2 让用户输入一段字符串,计算字符串中有多少A字符的个数。有多少个就在文件a.txt中写多少个’你好’
# 方法一
def count_num(arg):
count = 0
for i in arg:
if i == 'A':
count += 1
return count
content = input('请输入:') # hhhhhhhdfAAAAAAAAAAAFSDZG
val = count_num(content)
print(val) # 11
val = int(val)
f = open('a.txt',mode = 'w',encoding = 'utf-8')
for i in range(0,val): # 前取后不取 等价于for i in range(val):
f.write('你好')
f.close()
# 方法二
def count_num(arg):
count = 0
for i in arg:
if i == 'A':
count += 1
return count
def write_file(line):
if line == 0:
return False # 函数执行过程中,一旦遇到return,则停止函数的执行
f = open('a.txt', mode='w', encoding='utf-8')
f.write(content)
f.close()
return True
message = input('请输入:') # hhhAAhhhAAhdfAFSDZGAA
val = count_num(message)
print(val) # 7
content = '你好'* val
write_file(content)
status = count_num(message)
if status:
print('写入成功')
else:
print('写入失败')
练习3 写函数,计算一个列表中有多少个数字,打印:列表中有%s个数字。
提示:type(‘x’) == int 判断是否是数字。
# 方法一:
def num_count(list):
count = 0
for item in list:
if type(item) == int:
count += 1
return count
num_count(['gf',1,55,7,'fggh'])
num = num_count(['gf',1,5,7,'fggh'])
message = '列表中有%s个数字'%(num,)
print(message)
# 方法二:
def num_count(list):
count = 0
for item in list:
if type(item) == int:
count += 1
message = '列表中有%s个数字' % (count,)
print(message)
num_count(['gf',1,55,7,'fggh'])
练习4 写函数,计算一个列表中偶数索引位置的数据构造成另外一个列表,并返回。【注】题目没说要打印,因此不需要print()
# 方法一:
def new_list(list):
new_list = list[::2]
return new_list
new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh'])
# 方法二:
def new_list(list):
new_list =[]
list_len = len(list)
for i in range(0,list_len):
if i % 2 == 0:
new_list.append(list[i])
return new_list
new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh'])
# v = new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh'])
# print(v)
练习5 阅读文件,将文件的内容构造成指定格式的数据,并返回,打印出来。
'''
a.log文件
alex|123|18
eric|uiuf|19
...
目标结构:
a. ['alex|123|18','eric|uiuf|19'] 并返回
b. [['alex','123','18'],['eric','uiuf','19']] 并返回
c. [
{'name':'alex','pwd':'123','age':'18'}
{'name':'eric','pwd':'uiuf','age':'19'}
]
...
'''
def write_file():
file_w = open('a.log',mode = 'w',encoding = 'utf-8')
content = 'alex|123|18\n'+'eric|uiuf|19\n'
file_w.write(content)
file_w.close()
def list_str():
file_r = open('a.log', mode='r', encoding='utf-8')
a = []
for line in file_r:
line = line.strip()
a.append(line)
print(a) # 如果下面有print,此处就不用写了,如果下面没有print,此处就写
file_r.close()
return a
def list_list():
file_r = open('a.log', mode='r', encoding='utf-8')
b = []
for line in file_r:
line = line.strip()
result = line.split('|')
b.append(result)
print(b) # 如果下面有print,此处就不用写了,如果下面没有print,此处就写
file_r.close()
return b
def list_dict(iii):
file_r = open('a.log', mode='r', encoding='utf-8')
a = []
b = []
c = []
for line in file_r:
line = line.strip()
a.append(line)
result = line.split('|')
b.append(result)
file_r.close()
for i in range(0,2):
info = {}
info['name'] = b[i][0]
info['pwd'] = b[i][1]
info['age'] = b[i][2]
# print(info)
info.update(info)
c.append(info)
# 如果下面有print,此处就不用写了,如果下面没有print,此处就写
if iii == 'a':
print(a)
elif iii == 'b':
print(b)
elif iii == 'c':
print(c)
return a,b,c
# list_str()
# list_list()
list_dict('a')
list_dict('b')
list_dict('c')
4 作用域
1.python 中:
● py文件:全局作用域 全局变量以后必须要大写
● 函数:局部作用域
a = 1 # 全局变量
def s1(): # 局部变量
x1 = 666
print(a) # 1
print(b) # 2
print(x1) # 666
b = 2
print(a) # 1
s1() # 若s1 放在b的前面,报错
a = 888
def s2():
print(a,b) # 888 2
s1() # s2()函数内部调用另一个函数 s1()的前提是,s1()在全局上有定义
s2()
c = a + b
print(c)
######## 执行顺序:a = 1--> b = 2--> print(a)--> s1() [print(a)-> print(b) ->print(x1)] --> s2() print(a,b) --> c = a + b -->print(c)
2.函数的嵌套
# 函数的嵌套
x = 10
def func1():
x=9
print(x)
def func2():
x=999
print(x)
print(x)
func2()
func1() # 先执行func1() 9 --> print(x) 9 -->func2() 999
x = 10
def func1():
x=8
print(x)
def func2():
print(x)
func2()
x = 9
func2()
x = 10
print(x)
func1() # 8-->8--> 9--> 10
name = 'oldboy'
def func():
name = 'alex' # 在自己作用域再创建一个这样的值,无法覆盖父级的值
print(name) # alex
func()
print(name) # oldboy
name = [11,2,33,11]
def func():
name.append('alex') # 不是重新赋值,但是可以对可变类型【列表、字典】修改
print(name) # [11, 2, 33, 11, 'alex']
func()
print(name) # [11, 2, 33, 11, 'alex']
3.global 如果非要对全局变量进行重新赋值,即使函数有嵌套,也是对全局变量修改
# 情况一:
name = 'oldboy'
def func():
global name
name = 'alex'
print(name) # alex
func()
print(name) # alex
# 情况二:
name = 'oldboy'
def func():
name = 'alex'
print(name) # alex
def inner():
global name
name = 999
inner()
func()
print(name) # 999
4.nonlocal 找到上一级进行修改
name = 'oldboy'
def func():
name = 'alex'
def inner():
nonlocal name
name = 999
inner()
print(name) # 999
func()
print(name) # oldboy
5.总结:
● 一个函数是一个作用域
● 作用域中查找数据规则:优先在自己的作用域查找,自己没有就去“父级”–> 下一级“父级” --> 直到全局。全部没有就报错。
● 局部可以用全局的,全局不能用局部的
5 递归
● 本质:函数自己调用自己,效率不高。【默认递归次数是1000次】
def func():
print(1)
func()
func() # 不停的循环打印 1 ,最多打印 1000 次
def func(i):
print(i)
func(i+1)
func(1) # 打印 1 2 3 4 ...
def func(a,b):
print(b)
func(b,a+b)
func(0,1) # 1 1 2 3 5 8 13 21 ...