函数当写的代码有规律地重复时,这时候就需要考虑定义一个函数,将这些代码抽离定义成一个函数,方便调用。Python提供了很多内置的函数,可以根据需要调用相应的函数来实现想要的功能。同样,Python也可以灵活自定义函数。调用函数在介绍如何定义函数之前,先说说如何调用函数。Python提供了许多内置函数,所有这些函数都可以直接调用。包括上一节,其实也有调用函数来实现一些功能的。这里是对函数调用的一般介绍。比如绝对值函数abs(),这个函数只接受一个参数。函数的使用可以查看官方文档:http://docs.python.org/3/library/functions.html#abs也可以通过help(abs)查看abs函数的帮助信息交互式命令行。现在尝试调用abs()函数:>>>abs(-1)1>>>abs(1)1因为abs只接受一个参数,如果传入的参数个数不为1,会报TypeError错误报告,消息错误消息也将在:>>>abs(-1,1)Traceback(mostrecentcalllast):File"",line1,inTypeError:abs()takesexactlyoneargument(2given)此处,abs()函数仅接受一个参数,但提供了两个参数。abs()的参数接收一个值。如果输入类型错误,也会报错:>>>abs('1')Traceback(mostrecentcalllast):File"",line1,inTypeError:badoperandtypeforabs():'str'此处给出的错误消息表明str不是可接受的类型。这是函数调用,还有一些地方需要注意。了解函数调用需要的几个参数,以及参数的类型。定义一个函数下面说一下函数的定义。def语句用于函数定义,后面是函数名,括号,括号内包含的参数,还有一个冒号,然后在缩进的块中写上函数体。如果有返回值,则使用return语句返回。还是以绝对值为例,这里是自定义函数实现:defmy_abs(num):ifnum>=0:returnnumelse:return-num执行return时执行函数,直接返回结果.例子中简单的使用了条件判断,非常复杂的逻辑可以通过条件判断和函数内部的循环来实现。有些函数没有返回语句。但是函数执行后,也会返回结果,只是结果为None。所以returnNone也可以写成return。现在我们尝试调用我们自己的函数my_abs:>>>my_abs(1)1>>>my_abs(-1)1>>>my_abs('a')Traceback(mostrecentcalllast):File"",line1,inFile"",line2,inmy_absTypeError:'>='notsupportedbetweeninstancesof'str'and'int'Hereyouwillseethatwhentheparameteracceptsastring,it出现的错误信息与Python提供的abs错误信息不一样。这里我们添加了对参数的检查,只允许整数和浮点类型的参数。数据类型检查可以通过isinstance()函数来实现。>>>defmy_abs(num):...ifnotisinstance(num,(int,float)):...raiseTypeError("badoperandtype")...ifnum>=0:...returnnum...else:...return-num...尝试再次调用该函数:>>>my_abs('1')Traceback(最近调用最后一次):文件“”,第1行,在文件“”,第3行,在my_absTypeError中:错误的操作数类型这看起来更像abs()函数。pass语句有时候,你可能没有想好要写什么样的函数,而是想先定义它,然后再添加代码。这时候pass语句就派上用场了。pass语句可以用作占位符。你可以先把这条语句放在函数体中,这样你写的其他代码才能运行。等到后续有补充再去掉pass语句修改。例如:defno_idea():pass如果函数体中没有这样的pass语句,运行时会提示语法错误。返回多个值上面提到的自定义函数,包括带有pass语句(returningNone)的空函数,返回一个值。为了返回多个值,可以直接返回一个元组,例如:>>>defmy_func():...return1,2,3...>>>a,b,c=my_func()>>>a1>>>b2>>>c3上面的函数虽然看似返回了多个值,但实际上是先创建了一个元组,然后再返回。事实上,我们是使用逗号来生成元组,而不是括号。例如:>>>a=(1,2)#有括号>>>a(1,2)>>>b=1,2#没有括号>>>b(1,2)所以,这是定义早期返回多个值的函数实际上返回的是元组。如果赋值给单个变量,那么这个变量其实就是返回的元组本身:>>>d=my_func()>>>d(1,2,3)functionparameterspositionalparametersdefineafunctionfirst:>>>deffunc(a,b):...print('a={},b={}'.format(a,b))...>>>func(1,2)a=1,b=2这里,就是a和b,都是位置参数。调用时,将两个值依次赋值给参数a和b。默认参数继续使用上面的例子。在这里,我们只在调用时分配给a:>>>func(1)Traceback(最近一次调用last):File"",line1,inTypeError:func()missing1requiredpositionalargument:'b'这里是一条错误信息:调用参数缺少位置参数b。这时候可以考虑使用默认参数:>>>deffunc(a,b=2):...print('a={},b={}'.format(a,b))。..>>>func(1)a=1,b=2可以看到调用func(1)时,相当于调用了func(1,2)。这里有一些地方需要注意:必需的参数必须放在默认参数之前,否则会报错。默认参数必须指向一个不变的对象。第一点比较容易理解。如果默认参数在必填参数前面,则传入的值会根据参数的位置赋值给参数。比如下面的错误示例(下面的写法只是为了错误演示,不建议这样写。当然这样写也会报错):deffunc(a=1,b):returna,b假设我们这样调用逻辑上认为现在a已经有默认值了,直接给b赋值就可以了。但分配将按职位分配。比如调用func(2)时,实际上是把2赋值给了a,代替了原来的1,最后b还是缺赋值。第二点是它必须指向一个不可变对象。永远不要这样写代码:deffunc(a,b=[]):....如果这样写,后面会遇到很多麻烦。b是一个可修改的对象,这些修改会影响下次调用这个函数的默认值。例如:>>>deffunc(a,b=[]):...print(b)...returnb...>>>x=func(1)[]>>>x.append(2)>>>x.append('wow!')>>>x[2,'wow!']>>>func(1)[2,'wow!']func(1)时可以看到再次调用的时候,结果变了,这不是本意。如果真的需要使用列表,最好先使用None,然后在函数中使用相应的逻辑检查。当然在测试None的时候需要注意,使用is运算符很重要。deffunc(a,b=None):ifnotb:#不建议这样写,建议使用bisNone:而不是上面的b=[]不建议使用ifnotb:,如果是,None将被视为False,长度为0的字符串、列表、元组、字典等可能被视为False。这一点也要注意。可变参数上面提到的函数都有固定数量的位置参数。为了实现可以接受任意数量的位置参数的函数,可以使用*参数。例如:>>>deffunc(*nums):...sum=0...fornuminnums:...sum+=num...returnsum...>>>func(1,2)3>>>func(1,2,3)6这样就实现了可以传入任意多个参数的位置参数。关键字参数如果要接受任意数量的关键字参数,可以使用以**开头的参数。例如:>>>definfo(name,age,**kw):...print('name:',name,'age:',age,'other:',kw)...>>>info('三千年梦',0)name:三千年梦年龄:0other:{}>>>info('三千年梦',0,city='广州')name:三千年梦三千秋age:0other:{'city':'广州'}>>>info('三千梦',0,city='广州',gender='男')name:三千梦秋秋age:0other:{'city':'广州','gender':'男'}这样可以传入任意多个关键字参数,这里关键字参数允许传入0或者任何带有参数名的参数,函数内部都会自动形成一个dict,如上例所示。namedkeywordparameters命名关键字参数,其实就是把关键字参数放在一个*参数或者单个*后面,例如:>>>definfo(name,age,*,city):...print(name,age,city)...>>>info('大梦三千秋',0,city='广州')大梦三千秋0广州这里注意调用方式,必须传入参数名,如果没有参数的话name传入,会报错:>>>info('大梦三千秋',0,'广州')Traceback(mostrecentcalllast):File"",line1,inTypeError:info()takes2positionalargumentsbut3weregiven上面的提示说只需要2个位置参数,但是有3个传入参数。此时,由于缺少参数名称city,解释器将3个参数全部视为位置参数,而info函数只接受2个位置参数。参数顺序这里所说的参数有位置(必填)参数、默认参数、可变参数、关键字参数和命名关键字参数。但是需要注意参数的定义顺序:必需参数、默认参数、可变参数、命名关键字参数和关键字参数。上面的参数虽然可以组合,但是不推荐这样做,会导致理解性差。以上就是关于函数的定义、调用和函数参数的介绍。欢迎关注微信公众号《书所集录》