Day14、15:函数

函数

在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:。

 def my_abs(x):
     if x>=0:
         return x
     else:
         return -x

空函数

如果想定义一个什么事也不做的空函数,可以用pass语句:

 def nop():
    pass

pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

pass还可以用在其他语句里,比如:

 if age >= 18:
    pass

参数检查

修改my_abs的定义,对参数类型做检查,只允许整数和浮点型的参数。

数据类型的检查可以用内置函数isinstance()实现:

 def my_abs(x):
     if not isinstance(x, (int, float)):
         raise TypeError('bad operand type')
     if x >= 0:
         return x
     else:
         return -x

返回多个数

支持返回多个值。

 import math
 def move(x,y):
     nx = x+math.cos(y)
     ny = y-math.sin(x)
     return nx,ny
 r=move(10,122)
 print(r)

其实返回的是一个tuple!

函数参数

Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。

默认参数

可以在定义函数参数时,给参数一个初始值,调用时可以不给该参数赋值,函数会使用参数的默认值。

 def power(x,n=2):
  s=1
     while n>0:
         n=n-1
         s=s*x
     return s
 
 power(3)   >>> 9
 power(3,3)  >>> 27

设置默认参数时,有几点要注意:

一是必选参数在前,默认参数在后,否则Python的解释器会报错。

二是如何设置默认参数。

当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

用默认参数的好处:比如要通过调用一个函数输入一组数据,该数据有四个参数,而大部分人的后面两个参数相同,这时候用默认参数就可以节省大量时间。

当不按顺序提供部分默认参数时,需要把参数名写上。

例:

 # 定义
 def enroll(name,gender,age=22,city="tianjin")
 # 调用 ,不按顺序提供参数
 enroll('Bob','M',city='anqing')

可变参数

当参数个数不确定时,我们可以把参数作为一个list或tuple传进来。

 def calc(numbers):
     sum=0
     for n in numbers:
         sum=sum+n*n
     return sum    

调用时,需要先组装出list或tuple。

calc([1,2,3])

如果利用可变参数,这样写:

def calc(*numbers):
sum=0
for n in numbers:
sum=sum+n*n
return sum

只需要在参数名前加个*

调用时:

calc(1,2,3)

还有一种情况:

nums=[1,2,3]
#调用一个已定义好的list或tuple
calc(*nums)
#在名字前加*变为可变参数。

*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

关键字参数

可变参数允许传入0个或任意个参数,这些参数调用时自动组装成list。

关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数自动组装为一个dict(键——值)

加两个**

# 只传入可变参数
def person(name,age,**kw):
print('name',name,'age',age,'others:',kw)
print('Adam',22)

image-20211021114241642 `

# 传入任意个数的关键字参数
person('Bob',23, city ='Beijing')
person('Bob',23, city ='Beijing',gender='M')

image-20211021115055434

关键字参数有什么用?它可以扩展函数的功能。比如,在person函数里,我们保证能接收到nameage这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。

命名关键字参数

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。这种方式定义的函数如下:

def person(name,age,*,city,job)
print(name,age,city,job)

person('bob', 23, city='anqing', job='engineer')

image-20211021115743215

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

def person(name,age,*args,city,job):
print(name,age,args,city,job)


person('bob', 20,1, city='Beijing', job='Engineer')

image-20211021120741590

当命名关键字参数有默认值时,调用时可以省略该参数的赋值。

def person(name,age,*args,city='NanJing',job):
print(name,age,args,city,job)

person('bob', 20,1, job='Engineer')

image-20211021121330377

参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

def f1(a,b,c=0,*args,**kw):
print('a=',a,'b=',b,'c=',c,'args:',args,'kw=',kw)


def f2(a,b,c=0,*,d,**kw):
print('a=', a, 'b=', b, 'c=', c,'d:',d,'kw=', kw)

f1(1,2)
f1(1,2,3)
f1(1,2,3,'a','b')
f1(1,2,3,'a','b',x=99)
f2(1,2,3,d=99,x=99)

image-20211021122347381

还可以通过一个tuple和dict调用上述函数:

# 用list,tuple和dict调用:
args=[1,2,3,4]
kw={'d':99,'x':'#'}
f1(*args,**kw)

image-20211021122928306

# 用tuple和dict调用
args=(1,2,3)
kw={'d':99,'x':'#'}
f2(*args,**kw)

image-20211021123044520

所以对于任何函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

练习:

# 以下函数允许计算两个数的乘积,请稍加改造,变成可接收一个或多个数并计算乘积:
def mul(*args):
if len(args) == 0:
raise TypeError('请输入值:')
s = 1
for n in args:
s = s*n
return s


print(mul(1, 2, 3))
print(mul(1, 2, 3, 4))

小结

  • *args是可变参数,args接收的是一个tuple;

  • **kw是关键字参数,kw接收的是一个dict。

  • 以及调用函数时如何传入可变参数和关键字参数的语法:

  • 可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过*args传入:func(*(1, 2, 3))

  • 关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过**kw传入:func(**{'a': 1, 'b': 2})

  • 使用*args**kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。

  • 命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。

  • 定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*,否则定义的将是位置参数。

递归函数

汉诺塔:

def move(n,a,b,c):
if n==1:
print(a,' --> ', c)

else:
move(n-1,a,c,b)
move(1,a,b,c)
move(n-1,b,a,c)

 

posted @ 2021-10-21 23:04  027code  阅读(80)  评论(0)    收藏  举报