Python 函数进阶

高阶函数

First Class Object

      # 函数在Python 中是一等公民
      # 函数也是对象,可调用的对象
      # 函数可以作为普通变量,参数,返回值 等等

高阶函数

高阶函数是至少满足下面一个条件的函数 # 接受一个或多个函数作为参数 # 输出一个函数

内建函数

sorted(iterable[,key][,reverse])排序

# 返回一个新的列表,对一个可迭代对象的所有元素排序,排序规则为key定义的函数,reverse 表示是否排序翻转

# sorted(lst,key=lambda x:6-x) # 返回新列表

# list.sort(key=lambda x:6-x) # 就地修改

filter(function,iterable)

# 过滤可迭代对象的元素,返回一个迭代器

# function 一个具有一个参数的函数,返回bool

# 例如,过滤出数列中能被3 整除的数字

map(function, *iterables) --> map object

对多个可迭代对象的元素按照指定的函数进行映射,返回一个迭代器

柯里化 Currying

指的是将原来接受俩个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数的函数

z = f(x,y) 转换成 z = f(x)(y) 的形式

def add(x,y):
    return x + y
add(3,4)

def add(x):
    def _add(y):
        return x + y
    return _add
add(5)(6)

装饰器

def logger(fn):
    def wrapper(*args,**kwargs):
        print('begin')
        x = fn(*args,**kwargs)
        print('end')
        return x
    return wrappe

@logger  # add = logger(add)
def add(x,y):
    return x + y

print(add(4,5))

无参装饰器

# 它是一个函数

# 函数作为它的形参

# 返回值也是一个函数

# 可以使用@functionname 方式,简化调用

# 装饰器是高阶函数,但装饰器是对传入函数的功能的装饰(功能增强)

副作用

原函数对象的属性都被替换。

带参装饰器

# 它是一个函数

# 函数作为它的形参

# 返回值是一个不带参数装饰器函数

# 使用@functionname(参数列表)方式调用

# 可以看做在装饰器外层又加了一层函数

def copy_properties(src):
    def _copy(dst):
        dst.__name__ = src.__name__
        dst.__doc__ = src.__doc__
        return dst
    return _copy

def logger(fn):
    @copy_properties(fn) #wrapper = copy_properties(fn)(wrapper)
    def wrapper(*args,**kwargs):
        """I am wrapper"""
        print('begin')
        x = fn(*args,**kwargs)
        print('end')
        return x
    return wrappe

@logger #add = logger(add)
def add(x,y):
    """This is a function for add"""
    return x + y
print("name={},doc={}".format(add.__name__,add.__doc__))

文档字符串

python 的文档

Python 是文档字符串 Documentation Strings

在函数语句块的第一行,且习惯是多行的文本,所以多使用三引号

惯例是首字母大写,第一行写概述,空一行,第三行写详细描述

可以使用特殊属性__doc__访问这个文档

def add(x,y):
    """ This id a function of addition"""
    a = x + y
    return x + y

print(help(add))

print("name={}\ndoc={}".format(add.__name__,add.__doc__))
name=add
doc= This id a function of addition

Python 类型注解

Python 是动态语言,变量随时可以被赋值,且能赋值为不同的类型

Python 不是静态编译型语言,变量类型是在运行器决定的

# 如何解决这种动态语言定义的弊端

增加文档 Documentation String

函数注解

def add(x:int,y:int) -> int:
    """
    :param x:int
    :param y:int
    :return:int
    """
    return x + y
print(help(add))
print(add(4,5))
print(add('a','b'))

# Python 3.5 引入

# 对函数的参数进行类型注释

# 对函数的返回值进行e欸行注解

# 只对函数参数做一个辅助的说明,并不对函数参数进行类型检查

# 提供给第三方工具,做代码分析,发现隐藏bug

# 函数注解的信息,保存在__annotations__属性中

# Python 3.6 引入变量注解

functools 模块

@functools.wraps(wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER_UPDATES)

# 类似copy_properties 功能

# wrapped 被包装函数

# 元组WRAPPER_ASSIGNMENTS中是要被覆盖的属性

‘__modeule__’,'__name__','__qualname__','__doc__','__annotations__'

模块名,名称,限定名,文档,参数注解

# 元组WRAPPED_UPDATES中是要被更新的属性,__dict__属性字典

# 增加一个 __wrapped__属性,保留着wrapped函数

partial 方法:

偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回

从partial 生成的函数,是对原函数的封装

@functools.lru_cache(maxsize=128,type=False)

Least-recently-used 装饰器。lru, 最近最少使用。cache 缓存

如果maxsize设置为None,则禁用LRU 功能,并且缓存可以无限制增长。当maxsize 是二的幂时,LRU功能执行得最好。

如果typed 设置为True, 则不同类型得函数参数将单独缓存。

斐波那契数简单实现:

import functools

@functools.lru_cache()
def fib(n):
    if n < 3:
        return n
    return fib(n-1) + fib(n-2)

print([fib(x) for x in range(3)])

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券