函数:
概述:在一个完整的项目中,某些功能会反复使用,那么会将功能封装成函数,当要使用功能时,直接调用函数即。
优点:
一:简化代码结构,增加了代码的复用度(重复使用的程度)。
二:如果想修改某些功能,或者修改某些或调试bug,只需要修改某些函数即可。
定义函数:
def 函数名(参数列表):
语句
return 表达式
解释:
def:函数代码块以def关键字开始。
函数名:遵循标识符规则,是要使用的功能的函数名字。
参数列表(参数1,参数2,......,参数n):任何传入函数的参数和变量必须放在圆括号之间,用逗号分隔.函数从函数的调用者那里获取信息。如果没有参数,小括号也不能省略。
冒号:函数内容以冒号开始,并且缩进。
语句:函数封装的功能。
return:用于结束函数的,并返回信息给函数的调用者.return后面的语句是不用执行的。
表达式:即返回给函数的调用者的信息。
注意:最后的return 表达式,可以不写,相当于return None。
函数的调用:
格式:函数调用(参数列表)
函数调用的本质:实参给形参赋值的过程。
实参(argument):调用函数是给函数传递的数据,本质是值。
形参(parameter):定义函数是小括号中的变量,本质是变量。
参数的传递:
值传递:传递不可变类型。number,string,turple,boolean,函数内部改变这些类型,函数外部对应的值不会改变。
引用传递:传递可变类型。dict,list,set,函数内部改变这些类型,函数外部对应的值会改变。
关键字参数:允许函数调用时参数的顺序与定义不一致。
例如:
def myPrint(str,age)
print(str,age)
myPrint(age=18,str=’boboob’) :调用函数时age和str的顺序与形参的顺序不一致。
默认参数:调用函数是,如果没有传递参数,则使用默认参数。
例如:
def myPrint(str=’boboob’,age=0)
print(str,age)
myPrint()
上述调用仍未出错,因为当没有传递参数时,str默认为‘bobboob’,age默认为0
另外:若使用默认参数,最好将默认参数放在最后。
例如:
def myPrint(str,age=0)
print(str,age)
myPrint(‘boboob’)
不定长参数:
概念:能处理比定义时更多的参数。
加了星号(*)的变量args存放所有未命名的变量参数,如果在函数调用时,没有指定参数,它就是一个空元组。
例如:
def func1 (name,*args)
print(name)
for x in arr: #遍历name的所有内容
print(x)
func1(‘bob’,’boboob’,’bobboobob’)
此时name=’bob’,args=(‘boboob’,’bobboobob’)
如果变量前面加上两个星号(**),则要求实参必须使用关键字参数,变量kwags为字典类型。如果在函数调用时,没有指定参数,它就是一个空字典。
def func2(**kwags)
print(kwargs)
func2(x=1,y=2,z=3)
则kwages={‘x’:1,’y’:2,’z’:3}
下面这个函数可以接受任何类型的数据(若用关键字参数,则关键字参数应该全部在实参列表的右边)。
def func2(*args,**kwags)
print(args,kwargs)
func2(1,1,2,x=1,y=2,z=3)
此时agrs=(1,1,2) kwargs={‘x’:1,’y’:2,’z’:3}
匿名函数:
概念:不使用def这样的语句定义函数,使用lambda来创建匿名函数。
特点:
1:lambda只是一个表达式,函数体比def简单。
2:lambda的主体是一个表达式,而不是代码块,仅仅只能在lambda表达式中封装简单的逻辑。
3:lambda函数有自己的命名空间,且不能访问自由参数列表之外的或全局命名空间的参数。
4:虽然lambda是一个表达式且看起来与内联函数一样,但事实上它C和C++的内联函数(减少使用的栈空间)不同,lambda表达式不能达到此效果。
格式:lambda 参数1,参数2,......,参数n:expression
例如:
sum=lambda num,num2 : num1 + num2
功能:return返回表达式(num1+num2)的值,给到sum。
装饰器:是一个闭包,把一个函数当作参数返回一个替代版函数,本质上就是一个返回函数的函数。
用途:希望在不改变原函数的基础上给函数加上一些功能,这时候可以用装饰器这个技术。
#简单的装饰器:
#原函数定义:
def fun1():
print(‘rundrun’)
#装饰器定义:
def outer():
print(‘**********’)
func1()
#调用:
outer()
评价:虽然outer()函数起到了对fun1的装饰作用,但是没有返回函数,不符合装饰器的定义。
#若希望装饰器不仅仅能够作用于func1(),希望它能装饰更多的函数。
则:
#装饰器定义:
def outer(func):
print(‘********’)
func()
#调用:
outer(func1)
评价:虽然outer()函数起到了对任何函数的装饰作用,但是没有返回函数,不符合装饰器的定义。
#若希望装饰器返回函数:
#装饰器定义:
def outer(func):
def inner():
print(‘********’)
func()
return inner
调用:
func1=outer(func1)
评价:outer()函数不仅起到了对任何函数的装饰作用,并且返回装饰后函数inner,符合装饰器的定义,但是不够好。
#若希望装饰器返回函数,并装饰带有参数的原函数:
#原函数定义:
def func1(name):
print('my name is %s' %name)
#装饰器定义:
def outer(func):
def inner(name):
print(‘****************’)
func(name)
return inner
#调用:
new_func1=outer(func1)
new_func1('fish')
#简化调用方法:
def outer(func):
def inner(name):
print(‘****************’)
func(name)
return inner
#使用@符号将装饰器应用到函数。
@outer #相当于省略func1=outer(func1)
#原函数定义:
def func1(name):
print('my name is %s' %name)
#调用:
func1(‘fish’)
评价:这种装饰器起到了作用,但是只能装饰只有一个形参的函数,不通用。希望形参的数目不限,这样的要求才合理。
例如:以下装饰器可以装饰任何函数
#装饰器定义:
def outer():
def inner(*args,**kwargs):
#添加修饰的功能
return func(*args,**kwargs) #这里是先调用func函数,再返回func函数返回的#值。若是原函数无返回值也没有关系,它会返回元函数会返回None。
return inner #这是返回一个函数。
@outer
#原函数定义:
def func1(name,age):
print(‘my name is %s,my age is %d years old’ %(name,age))
return ‘aaaa’
#调用:
func1(‘fish’,18)
偏函数:
概念:有些函数参数有默认值,若希望在不改动原有函数的情况下,修改参数的默认值,则可以使用偏函数的概念。
例如:
int(str,base=10) 这个函数的参数base默认值为10,表示str字符串是十进制字符串。可以自己定义偏函数,令base默认值为2。
#手动定义偏函数:
def int2(str,base=2):
return int(str,base)
#调用:
int2(‘1010’)
#理论上函数不用自己定义,引入模块即可:import functools
int3=functools.partial(int,base=2)
int3和int2是一模一样的函数,int3的定义方式会更加简单。