调用函数

数据类型转换

  • int('123')``float('12.34')``str(123)``bool(1)

    定义函数

    空函数

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

    参数检查

  • 自己写函数时,如果要检查参数类型:

    1. def my_abs(x):
    2. if not isinstance(x, (int, float)):
    3. raise TypeError('bad operand type')
    4. pass

    返回多个值

  • Python函数返回的其实是个tuple,因为返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple

  • 函数执行完毕也没有return语句时,自动return None

    函数的参数

    默认参数

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

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

    1. def add_end(L=[]):
    2. L.append('END')
    3. return L
    4. add_end() #['END']
    5. add_end() #['END', 'END']
    6. #默认参数L也是一个变量,它指向对象[]

    可变参数

  • def calc(*args)在参数前面加一个*即定义为可变参数。如果num是一个list,那么*num表示将这个list中的所有元素作为可变参数传入函数中,在函数调用时自动组装为一个tuple

    关键字参数

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

    1. def person(name, age, **kw):
    2. print('name', name, 'age', age, 'other', kw)
    3. extra = {'city':'Beijing', 'job':'Engineer'}
    4. person('Jack', 24, **extra)
    5. #注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra

    命名关键字参数

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

  • def person(name, age, *, city, job):命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。否则将视为位置参数
  • 命名关键字参数必须传入参数名,如果没有传入参数名,调用将报错

    参数组合

  • 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数

    递归函数

  • 函数调用时通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以递归调用次数过多会导致栈溢出

  • 解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,可以把循环看成是一种特殊的尾递归函数 ```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) ```

  • return fact_iter(num - 1, num * product)仅返回递归函数本身,num - 1num * product在函数调用前就会被计算,不影响函数调用
  • 💡 Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题