python基础--匿名函数&高阶函数&装饰器

lambda表达式返回匿名函数

  • python使用lambda创建匿名函数,lambda的主题是一个表达式而不是代码块
  • 格式: lambda 参数 : 表达式,返回lambda函数,匿名函数的返回值即表达式的运算值
a = lambda x, y: x + y    # lambda表达式返回匿名函数,然后变量a指向此匿名函数
print(a)                  # lambda函数: <function <lambda> at 0x000001FE58231E18>
a(1, 2)                   # 返回:3


# 直接调用lambda匿名函数本身
(lambda x, y: x+y)(x=1, y=2)     # 返回:3


# lambda作为函数返回值
def test():
    return lambda x, y: x + y

b = test()
print(b)     # 函数类型:<function test.<locals>.<lambda> at 0x000001FE585A5730>
b(1, 2)      # 返回:3

高阶函数

  1. 函数作为参数值,应用广泛,类似于:f(g(x))
  2. 函数作为返回值,往往形成闭包,类似于:f(x)(y)
  • 关于闭包:
    • 有权访问另一个函数作用域内变量的函数都是闭包。
    • 闭包就是 一个函数引用另一个函数中的变量,因为变量被引用着所以不会被回收(正好印证了垃圾回收机制的引用计数机制)
    • 闭包影响的是变量的生命周期,因此可以用于封装一个私有变量,这是优点也是缺点,缺点就是不必要的闭包只会徒增内存消耗。

柯里化函数

  • 柯里化:将原来接受两个/多个参数的函数改为接受一个参数的函数,该函数返回嵌套在该函数里接收所有剩余参数的函数。
  • 柯里化函数的运行过程就是参数的收集过程,我们将每一次传入的参数收集起来,并在最里层的函数中进行处理。
  • f(x, y) 转化为 f(x)(y)
def add(x, y):
    return x+y

def currying_add(x):
    def inner_add(y):
        return x+y
    return inner_add       # 返回内嵌的函数

def currying_add(x):
    return lambda y: x+y   # 直接使用lambda表达式,返回匿名的函数

currying_add(4)(5)    # 同 add(4, 5)

python装饰器

  • 装饰器就是一个闭包,为了不影响现有的函数,将被装饰的函数作为参数传递给一个装饰器函数,并返回增强后的被装饰的函数。
  • 带参装饰器和无参装饰器
def logger(fn):
    def wrap(*args, **kwargs)
        ret = fn(*args, **kwargs)   # 闭包,fn函数没有被回收,所以fn就会替换指向add
        print('函数参数类型:{},{}'.format(args, wargs))
        return ret
    return wrap

# 语法糖: 等价于add = logger(add),add被包装函数替换
@logger    
def add(x, y):
  return x+y

foo = logger(add)    # 内嵌wrap函数
foo(1, 2)        # 实参为args,输出:函数参数类型:'(1, 2), {}',返回:3
foo(x=1, y=2)    # 实参为kwargs,输出:函数参数类型:'(), {x=1, y=2}',返回:3


add = logger(add) # 因为add作为实参传递给fn之后,fn被wrap引用所以fn并没有销毁,这里的add增强后的函数
add(1, 2)   # 此处的add是增强后的add
  • 带参数的装饰器
@router.get("/student2/list", response=List[StudentSchemaOut])
@paginate(MyPagination)
# listStudent = paginate(listStudent)
def listStudent(request, filters: FiltersSchema = Query(...)):
    query_set = lists(request, filters, StudentInfo)
    return query_set

def paginate(
    func_or_pgn_class: Any = NOT_SET, **paginator_params: DictStrAny
) -> Callable:
    """
    @api.get(...
    @paginage
    def my_view(request):

    or

    @api.get(...
    @paginage(PageNumberPagination)
    def my_view(request):

    """

    isfunction = inspect.isfunction(func_or_pgn_class)
    isnotset = func_or_pgn_class == NOT_SET

    pagination_class: Type[PaginationBase] = import_string(settings.PAGINATION_CLASS)

    if isfunction:
        return _inject_pagination(func_or_pgn_class, pagination_class)

    if not isnotset:
        pagination_class = func_or_pgn_class

    def wrapper(func: Callable) -> Any:
        return _inject_pagination(func, pagination_class, **paginator_params)

    return wrapper

使用functools的wrap实现日志记录装饰器

https://blog.csdn.net/weixin_44799217/article/details/118695357

https://blog.csdn.net/lzf9651/article/details/139641445

from functools import wraps


# 添加操作日志装饰器--不带参数的装饰器
def addLog(fn):
     """
     @api.get(...
     @addLog
     def my_view(request):

     """
     @wraps(fn)
     def wrapper(*args, **kwargs):
         create(data={"operate_module": "aaa"}, model=SkssLog)
         return fn(*args, **kwargs)
     return wrapper


# 添加操作日志装饰器---带参数的装饰器
def addLog(comment):
    """
    @api.get(...
    @addLog("添加日志")
    def my_view(request):

    """

    def log(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            create(data={"operate_module": comment}, model=SkssLog)
            return fn(*args, **kwargs)

        return wrapper
    return log

@property装饰器

  • python内置的@property装饰器就是负责把一个方法变成只读属性调用。
class A(object):
    
    _name = 'testA'

    @property
    def test(self):
        return self._name

    @property        # 定义对象的读取getter属性test2
    def test2(self):
        return self._age
 
    @test2.setter    # 定义对象的写setter属性
    def test2(self, age):
        self._age = age


a = A()
print(a.test)    # 把test()方法作为属性调用,不用加上小括号,返回:'testA'
print(a.test())  # 报错:TypeError: 'str' object is not callable
a.test2 = 24
print(a.test2)   # 返回:24
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。