函数

调用函数


函数名其实是指向函数对象的引用,因此可以直接把函数名赋值给一个变量。

 

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

定义函数

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

什么也不做,用来作为占位符。

def nop():
    pass

内置函数abs()会帮我们检查输入参数类型是否正确,不正确会raise TypeError,my_abs()函数可以通过内置函数isinstance()判断类型是否满足条件。

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

返回多个值,其实返回的是元组tuple,可以依次赋值给不同的变量。

import math
def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y + step * math.sin(angle)
    return nx, ny

x, y = move(100, 100, 2)

函数的参数

位置参数

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

默认参数

必选参数在前,默认参数在后,变化大的参数在前,变化小的在后。

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

默认参数有个最大的坑,演示如下:

def add_end(L=[]):
    L.append('end')
    return L

add_end()
add_end()

第一次调用得到['end'],第二次调用得到['end','end']。python函数在定义的时候,默认参数的值就被计算出来了,默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,下次调用时,默认参数的值就变了。

定义默认参数要牢记一点:默认参数必须指向不变对象!

修改后:

def add_end(L=None):
    if L is None:
        L = []
    L.append('end')
    return L

可变参数

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

#直接输入参数,可以是0个
calc(1,2,3)
calc()
#对于list,tuple,调用可变参数
nums = [1,2,3]
calc(*nums)

关键字参数

可变参数允许传入0个或多个参数,这些参数在函数调用时自动组成list,而关键字参数允许传入0个或多个含参数名的参数,自动组成dict。

def person(name, age, **kw):
    print('name: ', name, 'age: ', age, 'other: ', kw)

person('Wayne', 20, city='Beijing', job='Engineer')
#可以直接传入dict类型
extra = {'city':'Beijing', 'job':'Engineer'}
person('Wayne', 20, **extra)#kw获得extra的拷贝,对kw的改变不会影响extra

命名关键字参数

检查某一项是否出现在关键字参数里

def person(name, age, **kw):
    if 'job' in kw:
        pass
    if 'city' in kw:
        pass
    pass

但是调用者仍可以传入不受限制的关键字参数

person('Wayne', 20, city='Beijing', addr='chaoyang', zipcode=123456)

如果要限制关键字参数的名字,可以使用命名关键字参数,如只接收job和city作为关键字参数

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

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

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

上述五种参数可以混合使用,但要注意参数定义的顺序:必选参数,默认参数,可变参数,命名关键字参数,关键字参数

递归函数

要注意栈溢出,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。解决递归调用栈溢出的问题,可以使用尾递归进行优化,但大多数编程语言没有对尾递归做优化,python解释器也没有。

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)

 

posted @ 2020-03-03 17:25  WayneWW  阅读(172)  评论(0)    收藏  举报