Python标准库—函数式编程模块itertools/functools/operator

函数式编程模块

  1. itertools模块
  2. functools模块
  3. operator模块

itertools

  • itertools.count(start=0, step=1)

    创建一个迭代器,它从 start 值开始,返回均匀间隔的值。类似如下代码:

    def count(start=0, step=1):
        """
        count(5,5) -> 5 10 15 20 25 30 ...
        """
        n = start
        while True:
            yield n
            n += step
    
  • itertools.cycle(iterable)

    无限循环的迭代iterable中的元素。类似如下代码:

    def cycle(iterable):
        """
        cycle("ABC") -> A B C A B C A B C ...
        """
        data = list(iterable)
        while True:
            for d in data:
                yield d
    
  • itertools.repeat(object, times=None)

    创建一个迭代器,不断重复 object 。除非设定参数 times ,否则将无限重复。

    def repeat(obj, times=None):
        if times is None:
            while True:
                yield obj
        else:
            for i in range(times):
                yield obj
    
  • itertools.chain(*iterables)

    创建一个迭代器,它首先返回第一个可迭代对象中所有元素,接着返回下一个可迭代对象中所有元素,直到耗尽所有可迭代对象中的元素。类似如下代码:

    def chain(*iterables):
        """
        chain("ABC",[1,2,3]) -> A B C 1 2 3
        """
        for iterable in iterables:
            for elem in iterable:
                yield elem
    
  • itertools.combinations(iterable, r)

    返回由输入 iterable 中元素组成长度为 r 的子序列(iterable中元素长度为r的组合)。

    >>> import itertools
    >>> 
    >>> for combination in itertools.combinations("ABCD",3):
    ...     print(combination)
    ...
    ('A', 'B', 'C')
    ('A', 'B', 'D')
    ('A', 'C', 'D')
    ('B', 'C', 'D')
    
  • itertools.permutations(iterable, r=None)

    连续返回由 iterable 元素生成长度为 r 的排列。

    如果r为None,默认为len(iterable)。

    >>> for x in itertools.permutations("123"):
    ...     print(x)
    ...
    ('1', '2', '3')
    ('1', '3', '2')
    ('2', '1', '3')
    ('2', '3', '1')
    ('3', '1', '2')
    ('3', '2', '1')
    
  • itertools.compress(data, selectors)

    创建一个迭代器,它返回 data 中经 selectors 真值测试为 True 的元素(迭代器在两者较短的长度处停止)。大致相当于:

    def compress(data, selectors):
        """
        compress("ABCDEF",[0,0,1,1,0,1]) -> C D F
        """
        return (d for d, s in zip(data,selectors) if s)
    
  • itertools.filterfalse(predicate, iterable)

    创建一个迭代器,只返回 iterablepredicateFalse 的元素。如果 predicateNone,返回真值测试为False的元素(内置函数filter的相反操作)。相当于以下代码:

    def filterfalse(predicate, iterable):
        """
        filterfalse(lambda x:x%2, range(10)) -> 2 4 6 8
        """
        if predicate is None:
            predicate = bool
        for elem in iterable:
            if not predicate(elem):
                yield elem
    
  • itertools.islice(iterable, stop)

    itertools.islice(iterable, start, stop[, step])

    创建一个迭代器,返回从 iterable 里选中的元素。

    >>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(itertools.islice(L,5))
    [0, 1, 2, 3, 4]
    >>> list(itertools.islice(L,2,5))
    [2, 3, 4]
    >>> list(itertools.islice(L,2,7,2))
    [2, 4, 6]
    
  • itertools.zip_longest(*iterables, fillvalue=None)

    • 内置函数zip(*iterables)

      创建一个迭代器,从每个可迭代对象中收集元素,迭代持续到耗光最短的可迭代对象。

      >>> for d in zip("ABCD","123"):
      ...     print(d)
      ...
      ('A', '1')
      ('B', '2')
      ('C', '3')
      
    • zip_longest(*iterables, fillvalue=None)

      创建一个迭代器,从每个可迭代对象中收集元素。如果可迭代对象的长度未对齐,将根据 fillvalue 填充缺失值。迭代持续到耗光最长的可迭代对象。

      >>> for d in itertools.zip_longest("ABCD","123"):
      ...     print(d)
      ...
      ('A', '1')
      ('B', '2')
      ('C', '3')
      ('D', None)
      >>> 
      >>> for d in itertools.zip_longest("ABCD","123",fillvalue="*"):
      ...     print(d)
      ...
      ('A', '1')
      ('B', '2')
      ('C', '3')
      ('D', '*')
      >>>
      
  • itertools.takewhile(predicate, iterable)

    创建一个迭代器,只要 predicate 为真就从可迭代对象中返回元素。大致相当于:

    def takewhile(predicate, iterable):
        for x in iterable:
            if predicate(x):
                yield x
            else:
                break
    

functools

  • @functools.lru_cache(maxsize=128, typed=False)

    functools.lru_cache实现了备忘功能,它把耗时的函数结果缓存在字典里,所以函数的位置参数或关键字参数必须是可hash的。

    • 如果将maxsize设置为None,则禁用LRU功能,缓存可以无限制地增长;当maxsize是2的幂时,LRU功能表现最佳。
    • 如果typed设置为true,则将分别缓存不同类型的函数参数。例如,f(3)f(3.0)将被视为产生截然不同的结果而被缓存。

    如下,使用高速缓存实现计算有效Fibonacci数的示例:

    >>> from functools import lru_cache
    >>> @lru_cache()
    ... def fibonacci(n):
    ...     if n<2:
    ...             return 1
    ...     else:
    ...             return fibonacci(n-1)+fibonacci(n-2)
    ...
    >>> fibonacci(10)
    89
    >>> fibonacci(100)#如果不用lru缓存,则此列需要计算tooooloooooongtime
    573147844013817084101
    >>> [fibonacci(i) for i in range(10)]
    [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
    >>>
    
  • functools.partial(func, *args, **keywords)

    偏函数(Partial function)是通过将一个函数的部分参数预先绑定为某些值,从而得到一个新的具有较少可变参数的函数。

    例子:Django发送邮件——绑定from_email参数,简化代码

    import functools
    ...
    
    def _send_email(subject, message, from_email, recipient):
        send_email(subject, message, from_email, recipient)
    
    email_admin = functools.partial(_send_email, from_email="admin@example.com")
    market_admin = functools.partial(_send_email, from_email="market@example.com")
    market_system_account = functools.partial(_send_email, from_email=settings.EMAIL_HOST_USER)
    
    ...
    
  • functools.reduce(function, iterable[, initializer])

    reduce第一个参数function为一个函数,第二个参数iterable为一个序列。

    rudece函数作用是把iterable中的第1个和第2个元素代入function,得到一个值,并把这个值和iterable第3个元素作为参数传入function,以此类推…最终得到一个值。

    >>> import functools
    >>> import operator
    >>> functools.reduce(operator.add,range(100))
    4950
    >>> sum(range(100))
    4950
    
  • @functools.singledispatch

    将函数转换为单调度泛型函数。

    import functools
    
    @functools.singledispatch
    def single(arg):
        print(arg)
    
    @single.register(float)
    @single.register(int)
    def _(arg):
        if type(arg) is float:
            print("Float:",arg)
        else:
            print("Int:",arg)
    
    @single.register(complex)
    def _(arg):
        print("Complex(%r,%r)"%(arg.real,arg.imag))
    
    @single.register(str)
    def _(arg):
        print("Str:",arg)
    
    @single.register(list)
    def _(arg):
        print("List:",arg)
    
    >>> single(3)
    Int: 3
    >>> single(2.6)
    Float: 2.6
    >>> single("Hello world")
    Str: Hello world
    >>> single([1,2,3,4,5])
    List: [1, 2, 3, 4, 5]
    >>> single(complex(1,2))
    Complex(1.0,2.0)
    
  • @functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

    定义函数装饰器。

    例子:不使用functools.wraps装饰器

    def tracer(func):
        def wrapper(*args, **kwargs):
            """wrapper n!"""
            result = func(*args,**kwargs)
            print("%s(%r,%r)->%r"%(func.__name__,args,kwargs,result))
            return result
        return wrapper
    
    @tracer
    def factorial(n):
        """return n!"""
        return 1 if n < 2 else n*factorial(n-1)
    
    >>> factorial.__name__
    'wrapper'
    >>> factorial.__doc__
    'wrapper n!'
    

    @装饰器语句等价于factorial=tracer(factorial),即factorial=wrapper;由演示结果看出,最后的factorial函数对象变成了wrapper,而非factorial函数。

    例子:使用functools.wraps装饰器

    import functools
    
    def tracer(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            """wrapper n!"""
            result = func(*args,**kwargs)
            print("%s(%r,%r)->%r"%(func.__name__,args,kwargs,result))
            return result
        return wrapper
    
    @tracer
    def factorial(n):
        """return n!"""
        return 1 if n < 2 else n*factorial(n-1)
    
    >>> factorial.__name__
    'factorial'
    >>> factorial.__doc__
    'return n!'
    

operator

operator模块提供了一套与Python的内置运算符对应的高效率函数。

函数描述
operator.abs(x)abs(x)
operator.add(a,b)a+b
opeartor.mod(a,b)a%b
operator.mul(a,b)a*b
operator.lt(a,b)a<b
operator.le(a,b)a<=b
operator.eq(a,b)a==b
operator.ne(a,b)a!=b
operator.ge(a,b)a>=b
operator.gt(a,b)a>b
etc.等等
>>> import operator
>>> from functools import reduce
>>> 
>>> operator.add(1,2)
3
>>> reduce(operator.add,range(100))#累加
4950
>>> reduce(operator.mul,range(1,7))#阶乘6!
720
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值