函数

常用函数

类型转换

int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False

定义函数

def my_abs(x):
    # 检查参数类型 
    if not isinstance(x, (int, float)):
       # 当参数类型错误时  抛出错误
        raise TypeError("bad operate Params type")

    if x>0:
        return x
    else:
        return -x

print(my_abs("-333")) #TypeError: bad operate Params type

定义一个空函数

def nop():
    pass
# pass用作占位符 

返回多个返回值
返回的其实为单一一个值,一个元组,我们通过多个变量接收一个元组,按位置赋值

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, 60, math.pi / 6)
print(x, y)
151.96152422706632 70.0

若函数结束时没有return语句,就自动添加 return None

函数参数

python的函数定义简单,灵活度很大.除了正常的必选参数外,还能使用默认参数、可变参数、关键字参数。

参数组合

在Python中,可以使用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,但是参数的定义顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数

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)

默认参数

必选参数在前,默认参数在后

def my_power(x, n=2):
    total = 1
    for s in range(1,n+1):
        total = total*x
    return total

print(my_power(2))  # 4

定义默认参数时: 默认参数必须指向不变对象,否则可变对象会成为函数内静态变量会在多次调用时变化,影响函数调用结果

使用默认参数即可省略参数,降低调用难度

可变参数

当不确定参数的个数时,可以使用可变参数,可以传入任意个参数,包括0个参数

def my_sum(*numbers):
    sum=0
    for x in numbers:
        sum += x

    return sum

print(my_sum(1,2,3,4)) # 10
numbers = [1,2,3,4,5]
#通过给list 或者 tuple前加*  将其元素变为可变参数
print(my_sum(*numbers)) #15 

传入的可变参数在函数内部封装为一个元组

关键字参数

可以传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动封装为dict

def my_personFuc(name, age, **kw):
    print("name:", name, "age:", age, kw)

my_personFuc("lyy", 24, city="luoyang") #name: lyy age: 24 {'city': 'luoyang'}
my_personFuc("wt", 20) # name: wt age: 20 {}

kwDict={"city":"beijing"}
# 解构字典
my_personFuc("yt", "25", **kwDict) # name: yt age: 25 {'city': 'beijing'}

对于关键字参数,对于直接传入的参数,采用=而且key不能为str类似的字符串

命名关键字参数

#命名需要关键字 * ,在 * 之后的为命名关键字参数,
def my_keyPerson(name, age, *, city, job):
    print(name, age, city, job)

#命名关键字必须传入参数名 否则会报错 
my_keyPerson("lyy", 24, city="luoyang", job="iOS") # lyy 24 luoyang iOS

# 可以为可变参数隔开
def my_keyPerson1(name, age, *args, city, job):
    print(name, age, args, city, job)

# 明明关键字可以有缺省值,这样调用时候可以不传入city参数
def my_keyPerson2(name, age, *, city='Beijing', job):
    print(name, age, city, job)

递归函数

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况

# 递归函数
def fact(n):
    if n==1:
        return 1
    return n + fact(n - 1)

print(fact(10))  # 55
# 栈溢出
print(fact(1000))  #RecursionError: maximum recursion depth exceeded in comparison

#尾递归优化后
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)

目前包括Python在内的编程语言都没有做尾递归优化,因此类似上面的尾递归优化之后仍会导致栈溢出