Python中的函数、闭包、装饰器、lambda表达式、生成器和递归

Python中的函数、闭包、装饰器和lambda表达式

  • 函数
  • 闭包
  • 装饰器
  • lambda表达式
  • 生成器
  • 递归
  • 补充知识
  • 高阶函数

函数

文章对关于函数的所有知识进行了详细的总结和讨论,希望可以给大家带来帮助
首先是最简单的函数定义问题(后面附有代码的执行结果)

def myfunction(name):
  for i in range(3):
      print(f"I love my {name}!")
# myfunction(123)
print("\n")

下面是函数的健壮性和对于返回值的讨论

def div(x,y):
    if y == 0:
        return "除数不能为0"
    return x / y        # 函数的返回值,使用return语句
# print(div(2,0))
# 如果函数没有被显示地返回一个返回值,则函数也会返回一个none值
print("\n")

函数的传入参数是有严格的对应关系的,否则输出结果就会让你意想不到

def myfunc(s,vt,o):
    return "".join((o,vt,s))
print(myfunc("我","打了","我爸"))
print(myfunc("我爸","打了","我"))
# 要注意函数形参和输出参数的位置一一对应关系
# 使用关键字参数
print(myfunc(o = "我",vt = "打了",s = "我爸"))
# 且普通的参数必须写在关键字参数之前
print("\n")

在这里插入图片描述

在未初始化的情况下可使用默认参数

def myfunc2(name1,name2 = "kk"):
    return "".join((name1,name2))
print(myfunc2("jj"))
print("\n")

在这里插入图片描述

补充一个冷门的知识点,“*”号左边是位置参数(即普通参数),
也可以是关键字参数,但它的右边一定要关键字参数

def abc(a,*,b,c):
    print(a,b,c)
print("\n")

下面是关于参数的收集功能的实例

def parameter(*argument):
    print("total number is {}".format(len(argument)))
    print("the first word is {}".format(argument[0]))
    print(argument)
parameter("我","叫","大沙比")
# 收集参数,其中的内部实现是通过元组来实现
# 利用的是元组的打包和解包的功能
print("\n")

Python中的函数、闭包、装饰器、lambda表达式、生成器和递归_第1张图片

注意这种函数写法的时候,对于a b的定义要显示地使用关键字参数
否则输入都会被归纳为前面的args元组中,函数自然就会报错了

def myfunc3(*args,a,b):
    print(args,a,b)
myfunc3(1,2,3,a = 4,b = 5)
print("\n")

在这里插入图片描述

可以使用字典的写法建立键值对

def myfunc4(**args):
    print(args)
myfunc4(a = 1,b = 2,c = 3)
print("\n")

在这里插入图片描述

对于上面的的写法,有正向使用就有反向使用

def myfunc5(a,b,c,d):
    print(a,b,c,d)
kwargs = {'a':1,'b':2,'c':3,'d':4}
myfunc5(**kwargs)
print("\n")

在这里插入图片描述
注意局部作用域与全局变量的作用域,下面进行举例

x = 880
def myfunc6():
    global x
    x = 660
    print(x)
myfunc6()
print(x)
# 如果想打印外面的x,使用global,可以看到函数外面的x值被永久改变了
print("\n")

在这里插入图片描述
嵌套函数
且被嵌套的函数只能在外层函数之中被调用

def funcA():
    x = 520
    def funcB():
        x = 880
        print("in funcB,x = ",x)
    funcB()
    # return funcB    # 返回函数时,只需要返回其函数名即可
    print("in funcA,x = ",x)
funcA()     # 可以注意一下nonlocal的使用,可用之修改外层函数的变量
print("\n")

在这里插入图片描述

闭包

def funA():
    x = 880
    def funB():
        print(x)
    return funB
print(funA())
print(funA()())
funny = funA()
print(funny())
print("\n")

Python中的函数、闭包、装饰器、lambda表达式、生成器和递归_第2张图片
利用闭包进行次方的运算

def power(exp):
    def exp_of(base):
        return base ** exp
    return exp_of
square = power(2)   # 函数相当于使用到一半,会先保存之前输入的参数
cube = power(3)
print(square(2),square(5))
print(cube(2),cube(5))
print("\n")

在这里插入图片描述

再看一个例子进行深入的理解

def outer():
    x = 0
    y = 0
    def inner(x1,y1):
        nonlocal x,y
        x += x1
        y += y1
        print(f"现在,x = {x},y = {y}")
    return inner
move = outer()
print(move(1,2))
print(move(-2,2))
print("\n")

总结一下就是
1.利用嵌套函数的外层作用域具有记忆能力的特性
2.将内层函数作为返回值给返回
Python中的函数、闭包、装饰器、lambda表达式、生成器和递归_第3张图片

装饰器

函数名作为另一个函数的参数

import time
def time_master(func):
    print("开始运行程序")
    start = time.time()
    func()
    end = time.time()
    print("结束程序运行")
    print(f"一共耗费的时间为{(end-start):.2f}秒")
def myfunc7():
    time.sleep(2)
    print("hello!")
time_master(myfunc7)
print("\n")
# 或者用装饰器的方法:核心是 函数当参数+闭包
def time_master2(func):
    def call_func():
        print("开始运行程序")
        start = time.time()
        func()
        end = time.time()
        print("结束程序运行")
        print(f"一共耗费的时间为{(end - start):.2f}秒")
    return call_func    # 注意只返回的是函数名,不需要带括号
@time_master2
def myfunc8():
    time.sleep(2)
    print("hello!")
myfunc8()
print("\n")
# 可以看到结果和上一个程序的写法是一样的

Python中的函数、闭包、装饰器、lambda表达式、生成器和递归_第4张图片
多个装饰器一起使用的时候,顺序是自下向上调用

def add2(func):
    def inner():
        x = func()
        return x + 1
    return inner
def cube2(func):
    def inner():
        x = func()
        return x * x * x
    return inner
def square2(func):
    def inner():
        x = func()
        return x * x
    return inner
@add2
@cube2
@square2
def test():
    return 2
print(test())
print("\n")

在这里插入图片描述

多层嵌套函数时的装饰器,并给其传递参数

def llogger(msg):
    def time_master(func):
        def call_func():
            start = time.time()
            func()
            stop = time.time()
            print(f"{msg} consums totally {(stop - start):.2f}")
        return call_func
    return time_master

@llogger(msg="A")
def func9():
    time.sleep(1)
    print("A is running...")

@llogger(msg="B")
def func10():
    time.sleep(1)
    print("B is running...")

func9()
func10()
print("\n")

Python中的函数、闭包、装饰器、lambda表达式、生成器和递归_第5张图片

lambda表达式

一行流,lambda表达式
语法:lambda arg1,arg2,arg3,…,argN:expression
冒号左边是函数参数,冒号右边是函数表达式和返回值
首先写出普通函数的用法

def squareX(x):
    return x * x
print(squareX(3))
# 再用lambda表达式的写法
squareY = lambda y : y * y
print(squareY(3))
print(("\n"))

在这里插入图片描述

# lambda也可以用在列表中
y = [lambda x : x * x,2,3]
y[0](y[1])

生成器

每调用一次就提供一次数据,并且能记住之前的状态
在之前的状态下继续执行下去

def counter():
    i = 0
    while i <= 5:
        yield  i    # 产出的的意思,这里产出i
        i += 1
print(counter())
for i in counter():
    print(i,end=" ")    # 取消换行
print("\n")

在这里插入图片描述

递归

这是一个递归的阶层函数,程序运行的结果是120

def jieceng(n):
    if n > 1:
        return n * jieceng(n-1)
    else:
        return 1
print(jieceng(5),"\n")

接下来是汉诺塔问题

def hanoi(n,x,y,z):
    if n == 1:
        print(x,"-->",z)    # 如果只有1层,直接将金片从x移动到z
    else:
        hanoi(n-1,x,z,y)    # 将x上的n-1个金片从x移动到y
        print(x,"-->",z)    # 将最底下的金片从x移动到z
        hanoi(n-1,y,x,z)    # 将y上的n-1个金片移动到z
n = int(input("请输入金片的片数:"))
hanoi(n,'A','B','C')

Python中的函数、闭包、装饰器、lambda表达式、生成器和递归_第6张图片

补充知识

 函数文档 help + 函数 即help(function)
 写函数的时候,记得写函数的说明,形式如下
 '''
 功能:******
参数:******
返回值:******
'''
def times(s:str,n:int) -> str:
return str * n
冒号后面的str和int只是类型注释,表示希望输入的参数的类型

内省(注意使用面向对象的方法调用)
查看函数名 __name__
查看内容 __annotations__
查看函数文档__doc__

高阶函数

import functools
比如 reduce,partial(偏函数)等
wraps(func) 装饰器的进阶

你可能感兴趣的:(Python,开发语言,numpy,函数,python)