编程语言应用

注册

 

发新话题 回复该主题

IT编程Python开发基础系列参数 [复制链接]

1#

绝大多数函数接收一定数量的参数,然后根据实际调用时提供的参数的值的不同,输出不同的结果。前面我们说过,将函数内部的参数名字,定义得和外部变量的名字一样是一种不好的习惯,它容易混淆思维,甚至发生错误。通常我们定义和给函数传递参数是这样的:

x,y,z=1,2,3defadd(a,b,c):returna+b+cadd(x,y,x)#使用变量,传递参数add(4,5,6)#直接传递值也是可以的。

在上面的例子中,a,b,c叫做形式参数,简称形参。而x,y,z和4,5,6叫做实际参数,简称实参,也就是实际要传递的值。而我们通常讨论的参数,指的都是形参。

定义函数时,参数的名字和位置确定下来,函数的接口就固定了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。Python函数的参数定义灵活度非常大。除了正常定义的位置参数外,还可以使用默认参数、动态参数和关键字参数,这些都是形参的种类。

一、位置参数

也叫必传参数,顺序参数,是最重要的,也是必须在调用函数时明确提供的参数!位置参数必须按先后顺序,一一对应,个数不多不少的传递!

上面例子中的a,b,c就是位置参数,我们在使用add(4,5,6)调用时,就是将4传给a,5传给b,6传给c的一一对应传递。类似add(4,5,6,7)、add(4)和add(5,4,6)这种“画蛇添足”、“缺胳膊少腿”和“嫁错郎”类型的调用都是错误的。其中,add(5,4,6)的调用在语法上没问题,但是输出结果可能和预期的不一致。

注意ython在做函数参数传递的时候不会对数据类型进行检查,理论上你传什么类型都可以!

defadd(a,b,c):returna+b+cresult=add("haha",2,3)

但是,上面的add函数,如果你传递了一个字符串和两个数字,结果是弹出异常,因为字符串无法和数字相加。这就是Python的弱数据类型和动态语言的特点。在简单、方便的时候,需要你自己去实现数据类型检查。

Traceback(mostrecentcalllast):File"F:/Python/pycharm//func.py",line33,inmoduleresult=add("haha",2,3)File"F:/Python/pycharm//func.py",line31,inaddreturna+b+cTypeError:mustbestr,notint二、默认参数

在函数定义时,如果给某个参数提供一个默认值,这个参数就变成了默认参数,不再是位置参数了。在调用函数的时候,我们可以给默认参数传递一个自定义的值,也可以使用默认值。

defpower(x,n=2):returnx**nret1=power(10)#使用默认的参数值n=2ret2=power(10,4)#将4传给n,实际计算10**4的值

上面例子中的n就是个默认参数。默认参数可以简化函数的调用,在为最常用的情况提供简便调用的同时,还可以在特殊情况时传递新的值。但是在设置默认参数时,有几点要注意:

默认参数必须在位置参数后面!

如果你违反了这点,在语法层面直接是通不过的。

#这是一个错误的例子defpower(n=2,x):returnx**n

当有多个默认参数的时候,通常将更常用的放在前面,变化较少的放后面。

defstudent(name,sex,age,classroom="",tel="",address="..."):pass

在调用函数的时候,尽量给实际参数提供默认参数名。

defstudent(name,sex,age,classroom="",tel="",address="..."):passstudent(jack,male,17)#其它全部使用默认值student(tom,male,18,,,beijing)#全部指定默认参数的值student(mary,female,18,,tel=)#挑着来student(mary,female,18,tel=,beijing)#这是错误的参数传递方式student("mary","female",18,tel="",address="beijing")

注意最后两种调用方式,倒数第二种是错误的,而最后一种是正确的。为什么会这样?因为一切没有提供参数名的实际参数,都会当做位置参数按顺序从参数列表的左边开头往右匹配!

使用参数名传递参数

通常我们在调用函数时,位置参数都是按顺序先后传入,而且必须在默认参数前面。但如果在位置参数传递时,给实参指定位置参数的参数名,那么位置参数也可以不按顺序调用,例如:

defstudent(name,age,classroom,tel,address="..."):passstudent(classroom=,name="Jack",tel=66,age=20)

注意指定的参数名必须和位置参数的名字一样。

默认参数尽量指向不变的对象!

下面是国内某上市互联网公司Python面试真题:

deffunc(a=[]):a.append("A")returnaprint(func())print(func())print(func())

不要上机测试,仅凭代码,你能说出打印的结果吗?

很多同学可能会说,这还不简单,肯定是下面的结果啊:

[A][A][A]

真的是这样吗?错了!真正的结果是:

[A][A,A][A,A,A]

Why?为什么会这样?

因为Python函数体在被读入内存的时候,默认参数a指向的空列表对象就会被创建,并放在内存里了。因为默认参数a本身也是一个变量,保存了指向对象[]的地址。每次调用该函数,往a指向的列表里添加一个A。a没有变,始终保存的是指向列表的地址,变的是列表内的数据!我们可以测试一下:

deffunc(a=[]):print("函数内部a的地址为:%s"%id(a))a.append("A")returnab=func()print(此时b的值为:%s%b)print("函数外部b的地址为:%s"%id(b))print("-------------")c=func()print(此时c的值为:%s%c)print("函数外部c的地址为:%s"%id(c))print("-------------")d=func()print(此时d的值为:%s%d)print("函数外部d的地址为:%s"%id(d))

打印结果是:

函数内部a的地址为:此时b的值为:[A]函数外部b的地址为:-------------函数内部a的地址为:此时c的值为:[A,A]函数外部c的地址为:-------------函数内部a的地址为:此时d的值为:[A,A,A]函数外部d的地址为:

那么如何避免这个问题呢?

使用不可变的数据类型作为默认值!

deffunc(a=None)注意下面的if语句ifaisNone:a=[]a.append("A")returnaprint(func())print(func())print(func())

将默认参数a设置为一个类似None,数字或字符串之类的不可变对象。在函数内部,将它转换为可变的类型,比如空列表。这样一来,不管调用多少次,运行结果都是[A]了。

以上就是Python参数类型的详解,私信回复,免费领取Python编程全套学习资料,包含全套视频教程、项目源码、学习路线图等,赶快私信吧。

分享 转发
TOP
发新话题 回复该主题