08 Python 函数

1 调用函数

# 调用绝对值的函数
>>> abs(100)
100
>>> abs(-100)
100

# 求最大值函数
>>> max(1,2,3,5,6,-9)
6

1)数据类型转换

>>> int('124')
124
>>> int(23.12)
23
>>> float('123.34')
123.34
>>> str(1.234)
'1.234'
>>> bool(1)
True
>>> bool('')
False
>>> bool(0)
False

2)给函数起个‘别名’:

>>> a=abs # 变量a指向abs函数
>>> a(-9) # 通过a调用abs函数
9

2 定义函数

# 定义一个函数
def my_func(x, y, ....):
    执行语句
    return xxx

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

如果把 my_abs() 函数定义保存在了abstest.py文件中,那么,在该文件的当前目录下启动Python解释器,用 from abstest import my_abs 可以导入 my_abs() 函数。

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

def nop():
    pass

# pass可以用作占位符,在没想好写什么代码的时候,可以先放一个pass,让代码顺利运行起来。

2)参数检查

  • 调用函数时,如果参数的个数不对,Python解释器会自动检查出来,并抛出 TypeError 异常。
  • 当传入不恰当的参数时,内置函数abs会检查出参数错误,而我们定义的 my_abs 函数没有写参数检查代码,会导致 if 语句出错,出错信息和 abs 函数的不一样。
# 修改 my_abs() 函数,对参数类型进行检查
def my_abs(x):
    if not isinstance(x,(int, float)): # 判断x是否是整型或浮点型
        raise TypeError('bad operand type')
    if x>=0:
        return x
    else:
        return -x

3)函数可以返回多个值,实际上是返回一个tuple

3 函数的参数

1)位置参数

def add(x,y): # 参数x和参数y时位置参数
    return x+y

2)默认参数

def add(x,y=2): # y是默认参数,为2
    return x+y

# 调用函数
add(5)  # 可以不写y参数的值,此时默认y为2带入

注意:

  • 必选参数在前,默认参数在后
  • 有多个默认参数时,调用时可以按照顺序提供默认参数,也可以不按顺序提供默认参数,此时需要把参数名写上。
def add_students(name, gender, age=18, city='nanjing'):
    return name,gender,age,city

# 调用,按顺序
add_students('lisi','M',7) # age为7,city为默认的值
add_students('wanger','M', city='shanghai') # age为默认值,city为shanghai
  • 定义默认函数时,默认函数必须指向不变的对象!不能是List之类的。

3)可变参数

# 定义一个函数,计算平方和
def calc(*numbers): # 可变参数就是在普通参数前面加*
    sum=0
    for n in numbers:
        sum = sum + n * n
    return sum

# 调用函数
calc(1,2) # 结果是5
calc() # 结果是0

在函数内部,参数numbers接收到的是一个tuple,调用该函数时,可以传入任意个参数,包括0个参数。

# 如果已经有一个List或tuple,调用的方法
nums=[1,2,3]
calc(*nums) # 在List或tuple前面加一个*号,把list或tuple元素变成可变参数传进去

4)关键字参数

关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装成一个dict。

示例:

# 定义一个含关键字参数的方法
>>> def person(name, age, **kw):
...     print('name: ', name, 'age: ', age, 'other: ', kw)
...
# 调用方法,传入必要参数
>>> person('lisi',30)
name:  lisi age:  30 other:  {}
# 调用方法,传入关键字参数
>>> person('zhangsan',34,city='nanjing')
name:  zhangsan age:  34 other:  {'city': 'nanjing'}
# 调用方法,传入一个dict
>>> ex={'city':'shanghai','sex':'F'}
>>> person('wanger',23,**ex)
name:  wanger age:  23 other:  {'city': 'shanghai', 'sex': 'F'}

5)命名关键字参数

如果要限制关键字参数的名字,可以用命名关键字参数。

示例:

# 定义方法,带有命名关键字参数
>>> def user(name,age,*,sex,city):
...     print(name,'\t',age,'\t',sex,'\t',city)
...
# 调用方法,传入命名关键字参数,此参数名要和方法定义中的相同
>>> user('lisi',23,sex='f',city='nanjing')
lisi     23      f   nanjing
# 调用方法,传入的命名关键字参数的名字与定义时不同,出错!
>>> user('zhangsan',22,sexx='m',ci='beijing')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: user() got an unexpected keyword argument 'sexx'

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

# 定义函数
>>> def students(name, age, *args, id, sex):
...     print(name,age,args,id,sex)
...
# 调用函数
>>> students('lisi',22,'电子与通信工程','1班',id=123,sex='f')
lisi 22 ('电子与通信工程', '1班') 123 f

命名关键字参数必须传入参数名,否则报错!

命名关键字参数可以有默认值。

# 定义函数
>>> def person(name, age, *, city='nanjing', sex):
...     print(name,age,city,sex);
...
# 调用函数
>>> person('lisi',12,sex='f')
lisi 12 nanjing f

6)参数组合
在Python定义函数中,可以有多种类型参数组合。
参数定义的顺序是:
必选参数、默认参数、可变参数、命名关键字参数、关键字参数

# 定义函数f1
>>> def f1(a,b,c=0, *args, **kw):
...     print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
...
# 定义函数f2
>>> def f2(a,b,c=0, *, d, **kw):
...     print('a=',a,'b=',b,'c=',c,'d=',d,'kw=',kw)
...
# 定义tuple
>>> args=(1,2,3,4)
># 定义dict
>>> kw={'d':99, 'x':'#'}
# 调用函数f1
>>> f1(*args,**kw)
a= 1 b= 2 c= 3 args= (4,) kw= {'d': 99, 'x': '#'}
# 调用函数f2
>>> args=(1,2,3)
>>> f2(*args,**kw)
a= 1 b= 2 c= 3 d= 99 kw= {'x': '#'}

4 递归函数

在函数内部,可以调用其他函数,如果在一个函数在内部调用自己本身,这个函数就是递归函数。

示例:算阶乘

def fact(n):
    if n == 1:
        return 1
    return n * fact(n-1)

注意:

  • 使用递归函数,要防止栈溢出。所以,递归调用的次数不能过多。
  • 递归的优点是:定义简单、逻辑清晰。

1)尾递归

解决递归调用栈溢出的方法时通过尾递归优化。

尾递归是指,在函数返回的时候,调用自身本身,并且return语句不能包含表达式。这样,编译器或解释器可以把尾递归做优化,无论递归调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

示例:将上面求阶乘函数改成尾递归方式

def fact(n):
    return fact_iter(n,1)

def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num-1, num * product)

return fact_iter(num-1, num * product),仅仅返回递归函数本身,num-1和num * product在函数调用前就被计算,不影响函数使用。

注意:

  • 尾递归调用时,若做了优化,栈不会增长
  • 但是,大多数编程语言没有对尾递归进行优化,Python也是,所以,即使改成了尾递归方式,也会导致栈溢出
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值