函数定义
函数定义
函数定义:使用函数最基本的意义就是解决代码复用问题,解决代码冗余,解决代码可维护性差的问题。
函数的写法:
def test(): #定义函数名,括号里可以加参数,arg1,arg2用“,”分隔开。 """ 函数的基本描述信息 :return: """ print('hello world !') #这是函数的实现功能代码 return 1 #return返回值,后面可以跟任何数据类型。 test() #这是调用函数 这是无参函数,所以调用时也不参
空函数:设计程序功能函数,用pass代替函数体。
def test(): pass
函数的参数:括号里有值的,叫有参函数,没值的,叫无参函数。
无参函数:就是一些普通的语句。完全不依赖外部传入的值,就可以运行的函数,就是无参函数。
def print_line(): print("#"*13) def print_msg(): print("hello world !")
# 这就是无参函数
有参函数:就是依赖外部传入的值,才可以调用的函数,就是有参函数。最为直观的就是函数名括号里有值。
有参函数,在定义时有参数,那么在调用时,就需要传入对应的参数。 ret = test(1,5) 是函数调用的表达式形式。
def test(x,y): print("from test")
res = x+y #将x和y的结果赋给res return res #return返回的res是函数test的结果。 ret = test(1,5) #test函数定义时有参,调用时需要传参,test函数会拿到return的返回值,将返回值赋给一个变量ret,就可以打印结果了 print(ret)
函数的返回值:有三种情况,一种是无参函数。一种是返回一个值。还有一种是返回多个值。
注意:函数只能执行一个return的返回值。只要执行一个return,函数就执行完了。
无参函数不需要写return。返回一个值的,就是函数定义里面return返回的1,也可以返回多个值,因为return可以返回任何数据类型。
无参函数返回值:
def test(): """ 不写返回值的情况,结果是None。 :return: """ print('from the test') res = test() print(res) #打印结果是None。也算是有返回值的。
有参函数返回一个值:
def test(x,y): """ 有返回值的情况, 返回结果 :param x: :param y: :return: """ res=x if x>y else y return res res = test(1,4) print(res)
有参函数返回多个值:因为return可以返回任何数据类型。返回多个值是以元组的形式。
def test(x,y): """ return可以返回任何数据类型 :param x: :param y: :return: """ return 1,2,3,[1,2],{'a':1},{1,2,3} res = test(1,2) print(res)
res1,res2,res3,res4,res5,res6 = test(1,2) #这样就可以打印return返回的多个值
print(res1,res2,res3,res4,res5,res6)
函数的实参和形参:实参是调用函数时,传入的参数。形参是定义函数时,定义的参数。
形参就好比是变量名,实参就好比是变量明确的值。在实参传值给形参时,就是按参数位置传参。1传给x,5传给y。
注意:实参的数据类型要用不可变的数据类型,有数字,元组,字符串。
实参在函数调用使用后失效。
def test(x,y): #函数定义阶段,括号里的参数是形式参数 print(x) print(y) test(1,5) #调用函数时,括号内加的参数是实际参数
在实参中,还有一种赋值方法,就是按关键字传值。在传参中,直接赋予变量值。
def test(x,y): #函数定义阶段,括号里的参数是形式参数 print(x) print(y) test(x=3,y=4) #直接在传参中,赋予变量值。 test(y=7,x=8)
当然,关键字参数和位置参数可以混用。
注意:混用的注意事项是位置参数必须在关键字参数前面。
def test(x,y): #函数定义阶段,括号里的参数是形式参数 print(x) print(y) test(1,y=2) #调用函数时,括号内加的参数是实际参数 ##### 问题一:按位置传值必须在按关键字传值的前面 test(y=2,1) #报错,因为关键字参数在位置参数前面
对于参数,不能重复赋值。
def test(x,y): #函数定义阶段,括号里的参数是形式参数 print(x) print(y) test(1,x=1,y=2) #这就是对参数x多次赋值。会报错。
可变数据类型会改变原有的实参参数。这样操作会有副作用,他会改变全局变量。也就会导致可控性很差。(不推荐使用可变数据类型)
def test(x,y): #函数定义阶段,括号里的参数是形式参数 print(x) x.append(4) print(y) a = [1,2,3] #可变数据类型 b = 6 test(a,b) print(a,b)
注意:
形参角度:
一、位置参数:必须传值的参数,并且形参定义几个参数,就要传几个参数,传多或传少都不行。
def foo(x,y): print(x) print(y) # foo(1) #传少报错 # foo(1,2,3) #传多报错 foo(y=2,x=1)
二、默认参数:形参定义好的参数,在传值时,对于定义好的参数可以不传值,如果传值,新值会覆盖定义好的默认值。
def foo(x,y=1): #默认参数定义好y=1,那么在传参数时,对于y就可以不传 print(x) print(y) foo(1) #只传一个值,按位置给x,但结果依旧是1,1。 foo(1,2) #传两个值,按位置y的实参会覆盖默认的y=1,结果是1,2 foo(y=2,x=2) #按关键字传值,y的默认值也会被实参覆盖
注意:默认参数必须在位置参数后面。
#默认参数必须注意的问题是:默认参数必须放到位置参数的后面 def register(sex='male',name): #报错 name 应该在sex前面 print("name:", name) print("sex:", sex) register('george')
可变参数:*args,**kwargs。
*args:当位置参数传入多余的值,就交给*args处理,并且将这些多余的值,存成元组的形式。
def foo(x,*args): #args=(2, 3, 4, 5, 6, 6, 'a', 'b') print(x) print(args) foo(1,2,3,4,5,6,6,'a','b')
样例:应用*args。
#sum求和函数 def test_sum(*args): res = 0 for i in args: res+=i return res print(test_sum(1,2,3,4,5))
注意: *args 与位置参数和默认参数混用方式,是 *args 要放到位置参数后面。
def foo(x,*args,y=1): # *args在位置参数后面 print(x) print(y) print(args) foo(1,2,3,4,5,6,7,8,9,10,y=10000000)
**kwargs:当关键字传值传入多余的值,就交给**kwargs处理,并且将这些多余的值,存成字典的形式。
def foo(x,**kwargs): print(x) print(kwargs) foo(1,y=1,z=2)
如果函数foo()的参数是1,2,3,4,并且都有位置参数接收,那么**kwargs的结果就是一个空字典。
问题:当位置参数和*args以及**kwargs混用的时候。会出现位置参数后的值赋给*args处理,处理成元组。而之后的关键字参数会交给**kwargs处理,处理成字典。
def foo(x,*args,**kwargs): print(x) print(args) print(kwargs) foo(1,2,3,4,5,y=1,z=2)
*args和**kwargs的最终使用方式:位置参数的实参交给*args处理,关键字参数的实参交给**kwargs处理。
def foo(*args,**kwargs): print(args) print(kwargs) foo(1,1,1,1,1,1,a=1,b=2)
*args和**kwargs的应用:
def auth(name,password,sex='male'): print(name) print(password) print(sex) def foo(*args,**kwargs): #args=('george','123') kwargs={} print('from foo') auth(*args,**kwargs) # auth(*'george','123'), ###**{})--->auth('george','123') foo('george','123') foo(1,2,3,4,x=5,y=6) #报错 foo('george','456',sex='female') foo(name='george',password='789',sex='female')
------------- END --------------