python基础之---函数式编程

python基础之—函数式编程



一,函数式编程

1、函数作为参数

  • 将核心逻辑传入方法体,使该方法的适用性更广。
#高级函数
#函数也是一种数据
def foo(x):
    return 1
print(type(foo))

#回调参数 callback
#函数的参数,实际上是两个:形参和实参
#总结:函数也可以作为实参传入参数列表中

<class 'function'>

回调函数

#回调函数
#把一个函数传入另一个函数,传入的函数就是回调函数
def add(x,y):
    return x+y
def sub(x,y):
    return x-y
def mul(x,y):
    return x*y
def div(x,y):
    return x/y
x=100
y=200
print(add(x,y))

#工具函数

def calc(x,y,func):
    return func(x,y)

calc(x,y,add)#传入的add就是回调函数

#回调函数怎么体现回调
# 遍历:把一个数据容器中的数据全部取出来使用
# 设计一个工具函数:遍历列表中所有的元素,找出奇数拿出来使用,但是这个工具自己并不使用
#而是交给业务函数使用 这里的业务函数想干啥就干啥,这个业务函数就是回调函数

def find_odd(list,fn):
    for i in list:
        if i%2==1:
            fn(i)
x=[1,2,3,4,5,6,7,8,9,10]

def fn(i):
    print(i)
find_odd(x,fn)
300
1
3
5
7
9

2,函数作为返回值

我们可以通过闭包思想完成这一特性。

闭包是指引用了此函数外部嵌套函数的变量的函数,并把该函数作为返回值,是一种思想。

2.1 闭包定义

闭包必须满足以下三个条件:

  • 必须有一个内嵌函数
  • 内嵌函数必须引用外部函数中变量
  • 外部函数返回值必须是内嵌函数

2.2 闭包优缺点

优点

  1. 逻辑连续,当闭包作为另一个函数调用参数时,避免脱离当前逻辑而单独编写额外逻辑。
  2. 方便调用上下文的局部变量。
  3. 加强封装性,是第2点的延伸,可以达到对变量的保护作用。

缺点

引用在,空间不灭:闭包使得函数中的变量保存在内存中,内存消耗很大

2.3闭包案例面试分析

def fun(n=None,o=None):
  print(o)
  return {"fun":lambda m:fun(m,n)}

a=fun(0) 
a["fun"](1)
a["fun"](2)
a["fun"](3)

b = fun(0)["fun"](1)["fun"](2)["fun"](3)

c = fun(0)["fun"](1)
c["fun"](2)
c["fun"](3)

运行

None
0
0
0
None
0
1
2
None
0
1
1

自己分析

def fun(n=None,o=None):
  print(o)
  return {"fun":lambda m:fun(m,n)}
#定义了一个fun函数,包含两个参数,n和o,然后返回一个字典,
#字典里面有两个个键值对,第一个键值对是"fun",第二个键值对是lambda m:fun(m,n)

a=fun(0) #首先调用fun函数,传入0,得到n=0,o=None,所以输出、None
#返回一个字典,然后调用字典里面的"fun"键对应的值,
#也就是lambda m:fun(m,0),然后下一步
a["fun"](1)#调用"fun"字典,传入1,得到lambda 1:fun(1,0),然后回调得到fun(1,0)
#输出0

a["fun"](2)#调用"fun"字典,传入2,得到lambda 2:fun(2,0),然后回调得到fun(2,0)
#输出0
a["fun"](3)#调用"fun"字典,传入3,得到lambda 3:fun(3,0),然后回调得到fun(3,0)
#输出0

b = fun(0)["fun"](1)["fun"](2)["fun"](3)
#首先调用fun函数,传入0,得到n=0,o=None,所以输出、None
#返回一个字典,然后调用字典里面的"fun"键对应的值,
#也就是lambda m:fun(m,0),然后下一步
#然后调用"fun"字典,传入1,得到lambda 1:fun(1,0),然后回调得到fun(1,0)
#输出0,然后lambda 1:fun(m,1)
#然后调用"fun"字典,传入2,得到lambda 2:fun(2,1),然后回调得到fun(2,1)
#输出1,然后lambda 2:fun(m,2)
#然后调用"fun"字典,传入3,得到lambda 3:fun(3,2),然后回调得到fun(3,2)
#输出2,然后lambda 3:fun(m,3)



c = fun(0)["fun"](1)
#首先调用fun函数,传入0,得到n=0,o=None,所以输出None
#返回一个字典,然后调用字典里面的"fun"键对应的值,
#也就是lambda m:fun(m,0),然后下一步
#然后调用"fun"字典,传入1,得到lambda 1:fun(1,0),然后回调得到fun(1,0)
#输出0,然后lambda 1:fun(m,1)
c["fun"](2)
#然后调用"fun"字典,传入2,得到lambda 2:fun(2,1),然后回调得到fun(2,1)
#输出1,然后lambda 2:fun(m,1)
c["fun"](3)
#然后调用"fun"字典,传入3,得到lambda 3:fun(3,1),然后回调得到fun(3,1)
#输出1,然后lambda 3:fun(m,1)

伪代码

"""
global-->[
  标识符->fun是一个函数 也就是代码 它不运行的时候 就当做一个代码片段看待(文字)
  fun->def fun(n=None,o=None):
          print(o)
          return {"fun":lambda m:fun(m,n)}
  标识符a-是fun(0)的返回值
  a=fun(0)-->[
      标识符n=0
      标识符o=None
      print(o)==>打印None
      return {"fun":lambda m:fun(m,n)}

      O1>>>a["fun"](1)-->[
          标识符m=1
          return O2>>>fun(m,n)==fun(1,0)
      ]

      Q1>>>a["fun"](2)-->[
          标识符m=2
          return fun(m,n)== W1>>fun(2,0)
      ]
      R1>>>a["fun"](3)-->[
          标识符m=3
          return fun(m,n)==T1>>>fun(3,0)
      ]
  ]

  O1>>>a["fun"](1)

  O2>>>fun(1,0)-->[
      标识符n=1
      标识符o=0
      print(o)==>打印0
      return {"fun":lambda m:fun(m,n)}
  ]


  Q1>>>a["fun"](2)
  W1>>>fun(2,0)-->[
      标识符n=2
      标识符o=0
      print(o)==>打印0
      return {"fun":lambda m:fun(m,n)}
  ]

  R1>>>a["fun"](3)

  T1>>>fun(3,0)-->[
      标识符n=3
      标识符o=0
      print(o)==>打印0
      return {"fun":lambda m:fun(m,n)}
  ]



  b = fun(0)["fun"](1)["fun"](2)["fun"](3)
  标识符b=
  fun(0)-->[
     标识符n=0
     标识符o=None
     print(o)==>打印None
     return {"fun":lambda m:fun(m,n)}
     fun(0)["fun"](1)-->[
        标识符m=1
        return T1>>>fun(1,0)
     ]
  ]

  T1>>>fun(0)["fun"](1)>>>fun(1,0)-->[
     标识符n=1
     标识符o=0
     print(o)==>打印0
     return {"fun":lambda m:fun(m,n)}
     fun(0)["fun"](1)["fun"](2)-->[
            标识符m=2
            return fun(m,n)==fun(2,1) 
     ]
  ]

  fun(0)["fun"](1)["fun"](2)-->fun(2,1)-->[
     标识符n=2
     标识符o=1
     print(o)==>打印1
     return {"fun":lambda m:fun(m,n)}
     fun(0)["fun"](1)["fun"](2)["fun"](3)-->[
         标识符m=3
         return fun(m,n)==fun(3,2)
     ]
  ]


  fun(0)["fun"](1)["fun"](2)["fun"](3)-->fun(3,2)-->[
      标识符n=3
      标识符o=2
      print(o)==>打印2
      return 全局变量b的结果==>{"fun":lambda m:fun(m,n)}
  ]




  c = fun(0)["fun"](1)
  c["fun"](2)
  c["fun"](3)

  c变量-->
  fun(0)-->[
     标识符n=0
     标识符o=None
     print(o)==>打印None
     return {"fun":lambda m:fun(m,n)}
     fun(0)["fun"](1)-->[
        标识符m=1
        return fun(m,n)==fun(1,0)
      ]
  ]
  c-->fun(0)["fun"](1)-->fun(1,0)-->[
        标识符n=1
        标识符o=0
        print(o)==>打印0
        return {"fun":lambda m:fun(m,n)}
        c["fun"](2)-->[
             标识符m=2
             return fun(m,n)==fun(2,1)
        ]
        c["fun"](3)-->[
             标识符m=3
             return fun(m,n)==fun(3,1)
        ]
  ]

  c["fun"](2)-->fun(2,1)-->[
      标识符n=2
      标识符o=1
      print(o)==>打印1
      rerurn {"fun":lambda m:fun(m,n)}
  ]

  c["fun"](3)-->fun(3,1)-->[
      标识符n=3
      标识符o=1
      print(o)==>打印1
      rerurn {"fun":lambda m:fun(m,n)}
  ]
  
]
"""

简易分析a
在这里插入图片描述
简易分析b
在这里插入图片描述
简易分析c
在这里插入图片描述

3,装饰器

装饰器是Python对闭包思想的具体语法实现,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

  • 函数的装饰器的本质就是回调函数和闭包的结合
  • 装饰器本身是一个函数 它把被装饰的函数作为参数传入 然后把调用封装到内部的闭包中 返回值那个闭包
  • 未来调用被装饰器装饰过的函数 相当于在调用那个闭包
  1. 日志记录:可以使用装饰器来记录函数的输入、输出或执行时间。
  2. 认证和授权:装饰器可以用于检查用户是否有权限执行特定操作。
  3. 缓存:装饰器可以缓存函数的结果,从而提高执行效率。
  4. 参数验证:可以使用装饰器来验证函数的输入参数是否符合预期。
  5. 代码注入:装饰器可以在函数的执行前后注入额外的代码。

3.1基本装饰器

#装饰器
def decorator1(fun):
    def wrapper(*args,**kwargs):
        print("wrapper")
        return fun(*args,**kwargs)
        print("继续装饰")
    return wrapper
@decorator1
def fn():
    print("业务打印")
fn()

@decorator1
def fn3():
    print("fn3-66666")
fn3()


业务打印
wrapper
fn3-66666
在这里插入代码片

3.2带参装饰器

# 带参数的装饰器

def decorator2(num):
    def decorator(cb):
        def block():
            print("装饰函数的代码")
            for _ in range(num):
                cb()
        return block
    return decorator

@decorator2(2)
def fn():
  print("hello")
fn()#看起来是在调用fn 其实是在调用block

@decorator2(5)
def fm():
  print("world")
fm()
fm()
  • 案例 日志打印装饰器
#日志打印装饰器
def log(fun):
    def wrapper(*args,**kwargs):
        print("开始打印日志")
        fun(*args,**kwargs)
        print("结束打印日志")
    return wrapper
def diaoyong(a,b):
    print(a*b)


diaoyong(1,2)
2
  • 传参
def decorator2(num):
    def decorator(cb):
        def block(a,b,c):
            print("装饰函数的代码",a,b,c)
            for _ in range(num):
                cb()#cb就是被装饰的函数 必须具有相同的参数量
        return block
    return decorator

@decorator2(2)
def fn():
  print("hello")
fn(10,20,30)#看起来是在调用fn 其实是在调用block

@decorator2(2)
def fm():
  print("world")
装饰函数的代码 10 20 30
hello
hello

3.3装饰器链

# 装饰器链
def decorator1(cb):
    def block():
        print("block1")
        cb()
    return block
def decorator2(cb):
    def block():
        print("block2")
        cb()
    return block
@decorator1
@decorator2
def f3():
    print("f3")
f3()#执行decorator1装饰器的闭包 这个闭包中 有decorator2装饰器的闭包 中有f3函数
block1
block2
f3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值