Python3学习(7)--函数【Function】

来源:互联网 发布:dblp数据集 编辑:程序博客网 时间:2024/06/07 15:05

函数的目的是为了将一些复杂、繁琐、重复性极高的代码封装成一个方法,供使用者调用,使用者只关心函数本身,比如函数返回类型是什么,函数参数的个数以及参数类型和参数顺序是什么,而不关心函数内部的功能是怎么实现的(除了自己写的方法,自己使用,这种的话,使用者本身也是构造者),和大多数高级语言一样,Python也支持函数,不仅能很灵活的定义函数,而且还有着很多的内置函数,这些函数都非常有用,可以直接调用。


一、内置函数(注意Python是区分大小写的)

(1)绝对值函数-->abs(),一个参数,参数类型,int,float,均为无符号


(2)返回最大值-->max(arg1,arg2,arg3......) 多个参数,int,float,均为无符号,返回最小值-->min(arg1,arg2,arg3......)同理


(3)类型转换函数-->int(),float(),bool(),str(),参数均只有一个,且参数必须符合转换规则。



(4)为函数"起名"

假如我们让一个变量指向一个方法,当然这个方法前提是存在,如果我们用这个变量代替方法执行其所提供给外界的功能,那么我们就可以理解为,这个变量实际上就是这个方法的别名,当然,别名不止一个,而我们说的指向,其实就是变量用了函数名,说白了,其实指向的还是内存中的同一个区域,这个区域就是函数的地址。



二、定义函数(def)

根据Python内置的abs()的功能,我们也来自己写个类似的功能,看看,和系统内置的有什么区别,体验下自给自足的快感,哈哈!

首先,我们定义一个函数,取名my_abs,参数一个


然后我们写功能代码,大于0的我们返回(return)参数本身,小于0的我们让参数负一下并返回(return)


最后,我们测试一下,我们自定义的函数是不是很完美,没有一点破绽?


根据,以上的bug,我们来完善一下我们的函数,我们需要做的,就是在传入参数的第一时间,对参数进行判断,我们让参数类型只能是int和float;Python内置函数isinstance(object,(类型1,类型2,......))可以判断对象的类型是不是符合类型集合里面的类型,函数返回值bool类型

例如:


我们完善后的demo如下:

#!/usr/bin/env python3# encoding:utf-8#函数的定义 用def 来定义def my_abs(x):#一开始我们就做个参数类型判断 只能传int和floatif not isinstance(x,(int,float)):raise TypeError('bad operand type')if(x>0):return xelse:    return -xprint(my_abs(-12.5))print(my_abs(-10))print(my_abs(0))print(my_abs('2.0'))

我们看下,执行结果:



三、定义空函数

>>> def empty():#如果一个函数什么都不干 那么就用一个pass0占位,等以后想好了再来补充完
...     pass           #如果没有pass的话,会提示方法块错误
...
>>>

pass字面意义上理解,就是不考虑的意思,这里的pass语句,什么都不做,我们可以暂时定义一个函数,等我们想好这个函数要干什么的时候,我们就可以取消这个pass语句,用实际代码块来补充这个函数。

四、函数支持多值返回

比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标

#!/usr/bin/env python3# encoding:utf-8import mathdef move(x,y,step,angle=0):nx=x+step*math.cos(angle)ny=y-step*math.sin(angle)return nx,ny  #看似返回的是两个变量 其实返回多个值python的处理方式是返回tuple元组x,y = move(110,100,60,math.pi/6) #定义两个变量接收下返回的值print("x = %.2f,y = %.2f" %(x,y))

我们看下执行结果(move.py):



五、函数的参数

(1)参数设定默认值

#!/usr/bin/env python3# encoding:utf-8def power(x,n=2): #默认第二个参数等于2 意味着当传入一个参数的时候,实际计算的是这个数的平方s=1       #而不是报少一个参数的错误while n>0:s=s*xn=n-1return sprint(power(5))   #默认执行5**2 = 25print(power(5,3)) #        5**3 = 125



(2)默认参数的值必须指向不可变对象,否则,会出现意想不到的结果:

#!/usr/bin/env python3# encoding:utf-8#Python函数在定义的时候,默认参数L的值就被计算出来了,即[]#因为默认参数L也是一个变量,它指向对象[],每次调用该函数,#如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。#所以,定义默认参数要牢记一点:默认参数必须指向不变对象!def A(L=[]):    L.append('NULL')    return Ldef B(L=[]):    if len(L)== 0:#我们可以在这个地方判断下,如果L的长度等于0,让其有一个元素,是"NULL"            #而且,这个NULL,只会出现一次,多次调用B,不会出现A的情况。        L.append('NULL')    return Lprint("连续执行函数A的结果:")print(A()) #结果:['NULL']print(A()) #结果:['NULL', 'NULL']print("连续执行函数B的结果:")print(B()) #结果:['NULL']print(B()) #结果:['NULL']



(3)可变参数:

calc.py

#!/usr/bin/env python3# encoding:utf-8#calc函数计算一组数的和def calc(*numbers):#numbers表示这组数,*代表数的个数不定    sum = 0    for num in numbers:        sum = sum + num    return sumprint(calc(1,2,3))    #可以传三个参数print(calc(1,2,3,4,5))  #也可以传五个参数,甚至多个参数T= (1,2,3)L= (1,2,3,4,5)print(calc(*T))      #可以传一个tuple对象 ,前面带*号print(calc(*L))      #也可以传一个list对象,前面带*号




(4)关键字参数(相比较可变参数的一个*,关键字参数用2个*表示):

比如,我们拿身份登记这件事来说,姓名和年龄是必不可少的,但是如果需要其他的一些信息怎么办,而这个信息又可以是多条,这时候,我们就可以用关键字**来代替这些信息,如下:

#!/usr/bin/env python3# encoding:utf-8def regist(name,age,**others):print("姓名:",name,",年龄:",age,"其他注册信息:",others)extra  = {'性别':'男','职业':'现役NBA球员'}regist('詹姆斯',32,**extra)


(5)命名关键字:

相比较关键字的随意性,命名关键字,限制了关键字只能根据规定的名称来传,限定符是一个*号,*号后面跟关键字的名称,针对上面我们可以让关键字只能传入性别sex和工作job,传入其他信息视为不合法信息,如下,我们改下demo:

#!/usr/bin/env python3# encoding:utf-8def regist(name,age,*,sex,job):print("姓名:",name,",年龄:",age,"其他注册信息--性别:",sex,",工作:",job)regist('詹姆斯',32,sex='男',job='现役NBA球员')#类似于,一个变量占了一个位置,而传入的时候,根据情况给变量赋值regist('科比  ',38,sex='男',job="")             #如果某个命名关键字没有值,记得给空值,切记不要忘了写这个参数,否则会报错regist('appley',26,sex='男') #这个地方报错,缺少关键字'job'regist('appley',26,favorite='Apple',sex='男') #这个地方报错,丢失关键字'job'


(6)组合参数:

#!/usr/bin/env python3# encoding:utf-8def regist(name,sex="女",*wages,**others):    sum=0    for wage in wages:        sum=sum+wage;        print("姓名:",name,",性别:",sex,",第一季度工资总和:",sum,",其他基本信息:",others)     regist("李艳")#默认一个姓名,其余均为空extra = {'年龄':40,'工作':'包工头'}regist("张三","男",3000,2500,2900,**extra) #注意,关键字参数和命名关键字参数不能组合在一起,否则会报错



六、递归函数

函数调用本身,除非条件终止,否则函数一直调用自己,陷入死循环,举例说明,计算5的阶乘:

#!/usr/bin/env python3# encoding:utf-8def fact(n):    if n==1:#如果我们不加以条件限制,那么调用函数超出一定次数后,就会报错           #RecursionError: maximum recursion depth exceeded        return 1    else:        return n*fact(n-1)print("5! = ",fact(5))



本篇到这算是结束了,针对函数部分可能还有很多细节没有讲到,有些地方可能也讲的比较含糊,不过,我们可以通过实际应用中去发现这些不足,从而改善我们定义的函数,使其更加的完美,有些东西,实际用不到的话,你就算学了,过一段时间也会忘,所以说,好记性不如烂笔头,一定要学会记录,哪怕是一个简单的demo,日后都有可能对自己很有帮助!