Python基础之函数
1:函数
一:什么是函数
函数就是对某一个功能的代码,进行打包。类似于一修车师傅有工具箱一样,需要用什么工具直接拿来用就行。
二:为什么要有函数
当需要重复的用一些功能的时候,就可以直接调用,不用再复制粘贴
三:函数的分类
三.一:内置函数
print,id,map,filter...都是内置函数,你只需要怎么用就行。。。
三.二:自定义函数
就是你需要用什么功能,都是需要自己造
四:使用函数的优点
1,代码逻辑清晰,可读性好
2,不用写重复的代码
3,后面扩展容易,管理方便
2:函数的定义
一:如何定义函数
#语法
def 函数名(参数1,参数2,参数3,...):
'''注释'''
函数体
return 返回的值
#函数名要能反映其意义
def login():
name = input('请输入你的用户名:')
pwd = input("请输入的密码:")
if name == 'alex' and pwd = 'alexdsb':
print('登录成功')
else:
print("登录失败!")
#上述代码定义函数
二:函数的使用(先定义,后调用)
# 函数与变量的定义也差多,变量名如果不定义,调用变量就睡报错,函数名其实可以理解为变量名,不定义调用就报错
def login():
name = input('请输入你的用户名:')
pwd = input("请输入的密码:")
if name == 'alex' and pwd = 'alexdsb':
print('登录成功')
else:
print("登录失败!")
login() # 这就是调用函数
测试一
def f1():
print('from f1')
f2()
f1()
测试二
def f2():
print('from f2')
f1()
def f1():
print('from f1')
f2()
测试三
def f1():
print('from f1')
f2()
i
def f2():
print("from f2")
f1()
结果
测试一报错
测试二和测试三正常
结论:函数的使用,必须先要定义,后调用。
使用函数时,一定要明确区分定义阶段和调用阶段
三:函数定义解释器做了什么?
#只检测语法,不执行代码
也就说,语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在执行时才会知道
四:函数定义的三种形式
一:无参
应用场景仅仅只是执行一些操作,比如与用户交互,打印
def foo():
print('foo')
二:有参
需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值
def max_(arg1, arg2):
'''
参数必须是int类型
'''
if arg1 > arg2:
print(arg1)
else:
print(arg2)
三:空函数
设计代码结构
def login():
pass
def registry():
pass
........
3:调用函数
一:调用函数
函数的调用:函数名加括号
1 先找到名字
2 根据名字调用代码
def foo():
print("foo")
foo() # 这就是调用函数
二:函数返回值
一般没有定义返回值,函数默认的返回值为None
返回值要用关键字return
return 可以返回单个值,或者多个值(多个值是以元组的形式放回)
# 默认
def foo():
print('foo')
# 一个值
def foo():
print('foo')
return 'foo'
# 多个值
def foo():
print('foo')
return 0, 1, 2, 'foo'
三:函数调用的三种形式
一:语句形式
foo()
二:表达式形式
res = 3*len('helloword')
print(res)
三:函数作为另外一个函数的参数
res = max(max(1,30),3)
print(res)
4:函数的参数
一:形参与实参
形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定
def max_(arg1, arg2): # arg1与arg2是形参
'''
参数必须是int类型
'''
if arg1 > arg2:
print(arg1)
else:
print(arg2)
res = max_(100,101) # 100和101是实参
二:参数分类
一:位置参数
1:位置形参
1、位置形参:按照从左到右的顺序依次定义形参
特点:必须被传值,多一个不行少一个也不行
def foo(x, y, z):
print(x, y, z)
foo(1,2,3)
foo(1) # 报错
2:位置实参
2、位置实参:按照从左到右的顺序依次定义实参
特点:按照位置与形参一一对应
def bar(x,y):
print(x,y)
bar(3,1)
bar(1,3)
二:关键字实参
关键字实参:按照key=value的形式为指定的形参传值
特点:指名道姓为某个形参传值,可以完全打乱顺序
def foo(x,y):
print(x,y)
foo(x=1,y=2)
foo(y=2,x=1)
foo(2,1)
/
def bar(x,y):
print(x,y)
bar(1,2,x=101) # 报错
warning:关键字实参与位置实参可以混用,但是不能对同一个形参重复赋值
def func(x,y):
print(x,y)
func(x=1,3) # 报错
func(1,y=3)
func(y=3,1) # 报错
Warning:关键字实参必须放到位置实参右边
三:默认参数
默认参数:具有默认值的形参,指的是在定义函数阶段就已经为参数赋值,这意味着在调用函数阶段可以不用为默认参数传值
def func(x,y=1111):
print(x,y)
func(100)
func(100,101)
def func(y=111,x):
print(x,y)
定义的时候就保错了
warning:位置形参必需在默认参数左边
/
def func(name, names=[]):
# name = "张三"
# names=[]
names.append(name) # names=["张三"]
print(names)
func("egon")
func("张三")
func("李四")
默认形参的值是在函数定义阶段就被固定的,如果调用没有为默认形参传值,那么不会每次调用都重新赋值
函数的调用彼此之间应该做到没有关联,所以说默认形参的通常应该是不可变类型
def func(name, names=None):
if names is None:
names = []
names.append(name) # names=["张三"]
print(names)
func("egon")
func("张三")
func("李四")
四:可变长参数
一:可变长参数
可变长指的是在调用函数时,传入的实参个数不固定,而实参是为形参赋值的
所以对应着也应该有新的形参格式来负责接收不固定长度的实参
二:*args形参
def func(a,b,*args):
print(a,b,args)
func(1,2) # 1 2 ()
func(1,3,4) # 1 2 (4,)
func(3,4,5,6) # 3 4 (5,6)
func() # 报错
*形参名:*会负责把溢出的位置实参存成元组然后赋值给后面的形参名,形参名通过应该是args
三:**kwargs形参
def bar(x,y,z=11,**kwargs):
print(x,y,z,kwargs)
bar(1,2,a=1,c=2,d=3) #1 2 11 {'a': 1, 'c': 2, 'd': 3}
**形参名:**会负责把溢出的关键字实参存成字典然后赋值给后面的形参名,形参名通过应该是kwargs
四:*args实参
def foo(x,y):
print(x,y)
foo(*(2,3))
foo(*'he')
foo(*[1,2])
foo(*{'k1':1,'K3':3})
foo(*(1,2,3)) # 报错 这个是因为打散以后有三个值,但是函数的位置形参只有两个,所以报语法错误
warning实参中带*,*后跟的那个值应该是一个可以被for循环遍历的值。*会后面的那个值打散成位置实参(应该是可迭代数据类型)
五:**kwargs实参
def bar(x,y):
print(x,y)
bar(**{'k1':1,"k2":3})
bar(**{'name':"alen",'age':18})
bar(**{'name':'sb','gender':'female'})
实参中带**,**后跟的那个值应该是一个字典。**会后面的那个值打散成关键字实参
六:参数中混用*args,**kwargs
def foo(*args,**kwargs):
print(args,kwargs)
foo(1,2,3,4,5,6,x=1,b=3,c=4,d=1) # (1, 2, 3, 4, 5, 6) {'x': 1, 'b': 3, 'c': 4, 'd': 1}
foo(*[1,2,3,4,5],**{'x':1,'y':2}) # (1, 2, 3, 4, 5) {'x': 1, 'y': 2}
foo((1,2,3,4,5),{'k2':1,'k2':3})
/
def inner(x,y):
print(x,y)
def wrapper(*args,**kwargs):
inner(args,kwargs)
wrapper(1,2) # (1,2) {}
wrapper(x=1,y=2) # () {'x':1,'y':2}
wrapper(1,y=2) # (1,) {'y':2}
七:扩展
#5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递
可以保证,传入的参数中一定包含某些关键字
def foo(x,y,*args,a=1,b,**kwargs):
print(x,y)
print(args)
print(a)
print(b)
print(kwargs)
foo(1,2,3,4,5,b=3,cc=4,dd=5)
结果:
1
2
(3, 4, 5)
1
3
{'cc': 4, 'dd': 5}
5:函数的进阶应用
引子
在python中函数是第一类对象,简称函数对象
函数对象指的就是可以把函数当做变量一样去使用
1:赋值
def bar():
print('from bar')
print(bar)
f=bar
f()
2:可以当做参数传给另外一个函数
def func(aaa):
print(aaaa)
aaa()
def foo():
print("from foo")
func(foo)
3:可以当做函数的返回值
def foo(aaa):
return aaa
def bar():
print('from bar')
res=foo(bar)
print(res)
res()
4:可以当做容器类型的元素
def foo():
print("from foo")
l=[]
l.apend(foo)
l[0]()
# 示范
def login():
print('登录功能')
def register():
print('注册功能')
def transfer():
print('转账功能')
def charge():
print('充值')
def withdraw():
print('提现')
func = {
"1": ("登录",login),
"2": ("注册",register),
"3": ("转账",transfer),
"4": ("充值",charge),
"5": ("提现",withdraw)
}
while True:
print("0 退出")
for k,v in func.items():
print(k,v[0])
choice = input("请输入你的操作编号:").strip()
if choice == "0":
break
if choice in func:
func[choice][1]()
else:
print("输入的指令不存在")