函数

函数文档

定义函数


def testAbs(num):
    return abs(num)

print(testAbs(-1))

返回多个值

这其实是一个假象,返回的是一个tuple,而tuple可以省略括号,而多个变量可以同时接收一个tuple


def mulValueReturn():
    a = 12
    b = 13
    return a, b

a, b = mulValueReturn()

print(a)
print(b)

声明参数类型

def test(data: str):
    pass

声明返回值类型

from typing import Optional

# 返回值为字符串
def test1(data) -> str:
    return 'String'

# 返回值是int或者Node
def test1(data: int) -> Optional[int]:
    return None if data == 0 else data

默认参数

Python中可以使用 key=xxx 来跳过前面的默认参数


def children(name, gender, age=6, city='Shang Hai'):
    print(name)
    print(gender)
    print(age)
    print(city)

children('kk', '女', 7)
# 可以跳过第3个默认参数
children('ff', '男', city='Guang Zhou')

Python中的默认参数最好传不可变类型,否则多次调用,默认参数会发生变化


def testDefaultParams(end=[]):
    end.append('end')
    print(end)

testDefaultParams()
testDefaultParams()

可变参数

*args 其实就是把传入的n个参数打包成一个元祖

def mySum(*num):
    res = 0
    for x in num:
        res = res + x
    return res


print(mySum(1, 2, 3, 4, 5, 6))
test = [1, 2, 3]
print(mySum(test[0], test[1], test[2]))
# 如果本身就是一个列表或元祖,可以通过 *variable 的方式调用
print(mySum(*test))

关键字参数

**args 必须以key=value的方式调用,函数内部会自动转换成字典

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


person('kk', 7)
person('ff', 20, city='Shang Hai', gender='男')
testMap = {'hobby': 'coding', 'height': 188}
# 如果本身就是一个字典,可以通过 **variable 的方式调用
person('Zhang San', 18, **testMap)

命名关键字参数

使用 * 作为占位符,* 后面的参数必须以key=value的方式调用

跟关键字参数不同的是,函数内部不会自动转换成字段


def person(name, age, *, city, phone):
    print('name', name, 'age', age, 'city', city, 'phone', phone)


person('BestLove', 30, city='上海', phone='110')

如果参数中已经有一个可变参数,则不再需要单独使用 * 作为占位符了


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


person('BestLove', 30, city='上海', phone='110')
person('BestLove', 30, '可变', '加长', city='上海', phone='110')

参数组合

Python中可以用 必选参数、默认参数、可变参数、关键字参数和命名关键字参数 进行组合使用

但参数的顺序必须为:必选参数、默认参数、可变参数、命名关键字参数和关键字参数

不建议使用太多的组合,这样会使得代码的可读性变差

args -> args='xxx' -> *args -> **args -> *,args1,args2... 或 *args,args1,args2...(可变后面可以直接接命名关键字参数)

递归函数

def testRecursion(num):
    if num == 1:
        return 1
    return num * testRecursion(num - 1)


print(testRecursion(4))

高阶函数

def add(a, b, func):
    return func(a) + func(b)


print(add(2, -5, abs))

map 迭代器对象的每一个元素依次运行指定函数,最终返回一个迭代器对象

def myPow(num):
    return num * num


res = map(myPow, [1, 2, 3, 4, 5, 6])
print(list(res))

reduce 迭代器对象的每一个元素依次运行指定函数,每次运行的结果会作为下一次运行的第一个参数传入


from functools import reduce

# x为上次运行的结果,y为本次传入的参数
def add(x, y):
    print(x, '---', y)
    return x + y

# 如果没有初始值,第一次会传入2个参数,即:x=1,y=2
print(reduce(add, [1, 2, 3, 4]))
# 如果存在初始值,第一次会传入初始值和一个参数,即:x=0,y=1
print(reduce(add, [1, 2, 3, 4], 0))

常用的高阶函数还有很多,如:filter sorted 等

返回函数

不返回函数处理结果,只返回函数处理的过程

def lazySum(*args):
    def sum():
        res = 0
        for x in args:
            res += x
        return res

    return sum


func = lazySum(1, 2, 3, 4, 5)
print(func())

匿名函数

当一个函数返回了一个函数后,其内部的局部变量还被新函数引用

def count():
    fs = []
    for i in range(1, 4):
        def f():
            return i * i

        fs.append(f)
    return fs


for f in count():
    print(f())      # 输出9 9 9,因为当 f 调用的时候,i已经变成3了

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变

def count():
    def f(i):
        def g():
            return i * i

        return g

    fs = []
    for i in range(1, 4):
        fs.append(f(i))  # f(i)立刻被执行,因此i的当前值被传入f()

    return fs

for i in count():
    print(i())

lambda


# lambda 和 func 等效

f = lambda x: x * x

def func(x):
    return x * x

print(f(2))
print(func(2))

装饰器


import functools

# 两层嵌套
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)

    return wrapper

@log
def now():
    print('2020-12-12')

now()
print(now.__name__)

# 三层嵌套
def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator

@log('execute')
def now():
    print('2020-12-12')


now()
# 如果不加 @functools.wraps(func) now.__name__ 会变成 wrapper
print(now.__name__)

偏函数

通过 functools.partial 创建 8进制 int 强转的偏函数

偏函数与柯里化

  • 偏函数可以接受不只一个参数,它被固定了部分参数作为预设,并可以接受剩余的参数
  • 柯里化是将函数转化为多个嵌套的一元函数,也就是每个函数只接受一个参数
import functools

i = int('12345')
print(i)

i = int('12345', base=8)
print(i)

int8 = functools.partial(int, base=8)
i = int8('12345')
print(i)

results matching ""

    No results matching ""