概述
Task05:函数与Lambda表达式(2day)
基本上所有的高级语言都支持函数,Python也不例外。Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。
1.函数
1.调用函数
Python内置了很多有用的函数,我们可以直接调用。
要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。 调用函数的时候,如果传入的参数数量不对,会报TypeError的错误,并且Python会明确地告诉你:abs()有且仅有1个参数,但给出了两个:
>>> abs(-10)
10
>>> abs(1,2)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
abs(1,2)
TypeError: abs() takes exactly one argument (2 given)
如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息:str是错误的参数类型:
>>> abs('a')
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
abs('a')
TypeError: bad operand type for abs(): 'str'
而max函数max()可以接收任意多个参数,并返回最大的那个:
>>> max(1,4,3,2,5)
5
Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:
>>> int('123')
123
>>> str(1.23)
'1.23'
2.定义函数
定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。
Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。
函数的参数
a.位置参数
我们先写一个计算x2的函数:
对于power(x)函数,参数x就是一个位置参数。
当我们调用power函数时,必须传入有且仅有的一个参数x:
>>> def power(x):
return x*x
>>> power(5)
25
当然我们也可以定任何次方的函数:
>>> def power(x,n):
s=1
while(n>0):
n=n-1
s=s*x
return s
>>> power(5,3)
125
修改后的power(x, n)函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数x和n。
b.默认参数
新的power(x, n)函数定义没有问题,但是,旧的调用代码失败了,原因是我们增加了一个参数n,导致旧的代码因为缺少一个参数而无法计算平方:
>>> power(5)
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
power(5)
TypeError: power() missing 1 required positional argument: 'n'
Python的错误信息很明确:调用函数power()缺少了一个位置参数n。
这个时候,默认参数就派上用场了。由于我们经常计算x^2,所以,完全可以把第二个参数n的默认值设定为2:
>>> def power(x,n=2):
s=1
while(n>0):
n=n-1
s=s*x
return s
>>> power(5)
25
如果我们不想计算平方,想计算2次方以上的,就必须传入参数比如power(5, 3)。
从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,有几点要注意:
(1)必选参数在前,默认参数在后,否则Python的解释器会报错,因为如果默认参数放在必选参数前面,默认参数不需要给出,但是用户想要给必选参数赋值不想给默认参数赋值时,赋的值会自动给默认参数,导致了必选参选没有了值。
(2)当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
使用默认参数有什么好处?最大的好处是能降低调用函数的难度。
我们写一个学生信息注册的函数:
>>> def information(name,gender,age=6,city='Beijing'):
print('name:',name)
print('gender:',gender)
print('age:',age)
print('city:',city)
>>> information('syh','M')
name: syh
gender: M
age: 6
city: Beijing
因为学生的年龄和居住城市都变化不大,所以把这两个变量设为默认变量,只有与默认参数不符的学生才需要提供额外的信息。
有多个默认参数时,调用的时候,既可以按顺序提供默认参数,比如调用information(‘Bob’, ‘M’, 7),意思是,除了name,gender这两个参数外,最后1个参数应用在参数age上,city参数由于没有提供,仍然使用默认值。
也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll(‘Adam’, ‘M’, city=‘Tianjin’),意思是,city参数用传进去的值,其他默认参数继续使用默认值。
但默认参数有个需要注意的问题,使用时要注意:
>>> def add_end(L=[]):
L.append('end')
return L
>>> add_end([1,2,3])
[1, 2, 3, 'end']
>>> add_end()
['end']
>>> add_end()
['end', 'end']
当你使用默认参数调用时,一开始结果也是对的,但是,再次调用add_end()时,结果就不对了,Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
定义默认参数要牢记一点:默认参数必须指向不变对象!
要修改上面的例子,我们可以用None这个不变对象来实现,现在,无论调用多少次,都不会有问题:
>>> def add_end(L=None):
if L is None:
L=[]
L.append('end')
return L
>>> add_end()
['end']
为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
c.可变参数
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。我们举一个例子,计算数的平方和:
>>> def calc(*numbers):
sum=0
for n in numbers:
sum=sum+n*n
return sum
>>> calc(1,2,3)
14
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参。
当已知一个列表或者元组,需要去计算的话,我们有:
>>> a=[1,2,3]
>>> calc(a[0],a[1],a[2])
14
但是这样未免有些麻烦,有一个简便写法:
>>> calc(*a)
14
*a表示把a这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
d.关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。请看示例:
>>> def person(name,age,**kw):
print('name:',name,'age:',age,'other:',kw)
>>> person('SYH',20,gender='M',city='Tangshan')
name: SYH age: 20 other: {'gender': 'M', 'city': 'Tangshan'}
和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去,而且,dict也可以直接用**dict直接传进去,函数里面的改动并不会影响以外的dict:
>>> extra={'city':'Tanshan','job':'student'}
>>> person('SYH',20,**extra)
name: SYH age: 20 other: {'city': 'Tanshan', 'job': 'student'}
e.命名关键字参数
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
>>> def person(name,age,*,city,job):
print(name,age,city,job)
>>> person('Lusy',24,city='Beijing',job='Engineer')
Lusy 24 Beijing Engineer
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了,命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。
有时候命名关键字参数可以设置默认值,当然调用时就不需要传入参数了:
>>> def person(name,age,*,city='Beijing',job):
print(name,age,city,job)
>>> person('Jack',24,job='Engineer')
Jack 24 Beijing Engineer
参数组合
上面说到的命名关键字参数,如果前面没有可变参数,就需要在前面加上*,这样就间接的规定了参数组合的顺序:
必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
>>> def test(a,b,c=1,*args,d,**kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'd=',d,'kw =', kw)
>>> test(2,1,*a,d=5)
a = 2 b = 1 c = 1 args = (2, 3) d= 5 kw = {}
总结:对于函数的参数的设置,我们介绍了五种参数,必选参数、默认参数、可变参数、命名关键字参数和关键字参数
2.Lambda 表达式的应用
在 Python 里有两种函数:用 def 关键词的正规函数用 lambda 关键词的匿名函数匿名函数 (anonymous function)所谓匿名,即不再使用def语句定义一个函数。python 使用 lambda 来创建匿名函数。
lambda 只是一个表达式,函数体比def简单很多。
lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
lambda 函数没有所谓的函数名 (function_header),这也是它为什么叫匿名函数。
>>> sum=lambda arg1,arg2:arg1+arg2
>>> print(sum(10,20))
30
func=lambda *args:sum(args)
print(func(1,2,3,4,5))
15
Lambda 表达式的应用高阶函数 (high-order function) 在函数化编程 (functional programming) 很常见,主要有两种形式:
参数是函数 (filter, map)
返回值是函数 (closure)
下面,看看 map, filter的语法:filter(function, iterable) 过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。
>>> odd=lambda x:x%2==1
>>> templist=filter(odd,[1,2,3,4,5,6,7,8,9])
>>> print(list(templist))
[1, 3, 5, 7, 9]
map(function, iterable, …) 根据提供的函数对指定序列做映射
>>> m1=map(lambda x:x**2,[1,2,3,4,5])
>>> print(list(m1))
[1, 4, 9, 16, 25]
最后
以上就是传统导师为你收集整理的Task05:函数与Lambda表达式(2day)的全部内容,希望文章能够帮你解决Task05:函数与Lambda表达式(2day)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复