zoukankan      html  css  js  c++  java
  • operator模块和functools模块

    operator模块
    在函数式编程中,经常需要把算术运算符当作函数使用。例如,不使用 递归计算阶乘。求和可以使用 sum 函数,但是求积则没有这样的函数。 我们可以使用 reduce 函数(5.2.1 节是这么做的),但是需要一个函数 计算序列中两个元素之积。示例 5-21 展示如何使用 lambda 表达式解决 这个问题。
      示例 5-21 使用 reduce 函数和一个匿名函数计算阶乘
    from functools import reduce
    def fact(n):
        return reduce(lambda a, b: a*b, range(1, n+1))
    operator 模块为多个算术运算符提供了对应的函数,从而避免编写 lambda a, b: a*b 这种平凡的匿名函数。使用算术运算符函数,可以 把示例 5-21 改写成示例 5-22 那样。
       示例 5-22 使用 reduce 和 operator.mul 函数计算阶乘
    from functools import reduce
    from operator import mul
    def fact(n):
        return reduce(mul, range(1, n+1))
    operator 模块中还有一类函数,能替代从序列中取出元素或读取对象 属性的 lambda 表达式:因此,itemgetter 和 attrgetter 其实会自行构建函数。
    示例 5-23 展示了 itemgetter 的常见用途:根据元组的某个字段给元 组列表排序。在这个示例中,按照国家代码(第 2 个字段)的顺序打印 各个城市的信息。其实,itemgetter(1) 的作用与 lambda fields: fields[1] 一样:创建一个接受集合的函数,返回索引位 1 上的元素。   示例 5-23 演示使用 itemgetter 排序一个元组列表(数据来自示 例 2-8)
    metro_data = [
        ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
        ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
        ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
        ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
        ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
     ]
    
    from operator import itemgetter
    for city in sorted(metro_data, key=itemgetter(1)):
        print(city)
    如果把多个参数传给 itemgetter,它构建的函数会返回提取的值构成 的元组:
     
    >>> cc_name = itemgetter(1, 0)
    >>> for city in metro_data:
    ... print(cc_name(city))
    ...
    ('JP', 'Tokyo')
    ('IN', 'Delhi NCR')
    ('MX', 'Mexico City')
    ('US', 'New York-Newark')
    ('BR', 'Sao Paulo')
    itemgetter 使用 [] 运算符,因此它不仅支持序列,还支持映射和任何实现 __getitem__ 方法的类。
    attrgetter 与 itemgetter 作用类似,它创建的函数根据名称提取对 象的属性。如果把多个属性名传给 attrgetter,它也会返回提取的值 构成的元组。此外,如果参数名中包含 .(点号),attrgetter 会深 入嵌套对象,获取指定的属性。这些行为如示例 5-24 所示。这个控制 台会话不短,因为我们要构建一个嵌套结构,这样才能展示 attrgetter 如何处理包含点号的属性名。
      示例 5-24 定义一个 namedtuple,名为 metro_data(与示例 5- 23 中的列表相同),演示使用 attrgetter 处理它
    >>> from collections import namedtuple
    >>> LatLong = namedtuple('LatLong', 'lat long') # ➊
    >>> Metropolis = namedtuple('Metropolis', 'name cc pop coord') # ➋
    >>> metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long)) # ➌
    ... for name, cc, pop, (lat, long) in metro_data]
    >>> metro_areas[0]
    Metropolis(name='Tokyo', cc='JP', pop=36.933, coord=LatLong(lat=35.689722,
    long=139.691667))
    >>> metro_areas[0].coord.lat # ➍
    35.689722
    >>> from operator import attrgetter
    >>> name_lat = attrgetter('name', 'coord.lat') # ➎
    >>>
    >>> for city in sorted(metro_areas, key=attrgetter('coord.lat')): # ➏
    ... print(name_lat(city)) # ➐
    ...
    ('Sao Paulo', -23.547778)
    ('Mexico City', 19.433333)
    ('Delhi NCR', 28.613889)
    ('Tokyo', 35.689722)
    ('New York-Newark', 40.808611)
    ❶ 使用 namedtuple 定义 LatLong。
    ❷ 再定义 Metropolis。
    ❸ 使用 Metropolis 实例构建 metro_areas 列表;注意,我们使用嵌 套的元组拆包提取 (lat, long),然后使用它们构建 LatLong,作为 Metropolis 的 coord 属性。
    ❹ 深入 metro_areas[0],获取它的纬度。
    ❺ 定义一个 attrgetter,获取 name 属性和嵌套的 coord.lat 属性。
    ❻ 再次使用 attrgetter,按照纬度排序城市列表。
    ❼ 使用标号❺中定义的 attrgetter,只显示城市名和纬度。
     
    下面是 operator 模块中定义的部分函数(省略了以 _ 开头的名称,因 为它们基本上是实现细节): 
    >>> [name for name in dir(operator) if not name.startswith('_')]
    ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains',
    'countOf', 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt',
    'iadd', 'iand', 'iconcat', 'ifloordiv', 'ilshift', 'imod', 'imul',
    'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift',
    'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le',
    'length_hint', 'lshift', 'lt', 'methodcaller', 'mod', 'mul', 'ne',
    'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', 'setitem', 'sub',
    'truediv', 'truth', 'xor']
    这 52 个名称中大部分的作用不言而喻。以 i 开头、后面是另一个运算 符的那些名称(如 iadd、iand 等),对应的是增量赋值运算符(如 +=、&= 等)。如果第一个参数是可变的,那么这些运算符函数会就地 修改它;否则,作用与不带 i 的函数一样,直接返回运算结果。
    在 operator 模块余下的函数中,我们最后介绍一下 methodcaller。 它的作用与 attrgetter 和 itemgetter 类似,它会自行创建函 数。methodcaller 创建的函数会在对象上调用参数指定的方法,如示 例 5-25 所示。
      示例 5-25 methodcaller 使用示例:第二个测试展示绑定额外参 数的方式
    >>> from operator import methodcaller
    >>> s = 'The time has come'
    >>> upcase = methodcaller('upper')
    >>> upcase(s)
    'THE TIME HAS COME'
    >>> hiphenate = methodcaller('replace', ' ', '-')
    >>> hiphenate(s)
    'The-time-has-come'
     
    使用functools.partial冻结参数
     
    functools 模块提供了一系列高阶函数,其中最为人熟知的或许是 reduce,我们在 5.2.1 节已经介绍过。余下的函数中,最有用的是 partial 及其变体,partialmethod。
    functools.partial 这个高阶函数用于部分应用一个函数。部分应用 是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固 定。使用这个函数可以把接受一个或多个参数的函数改编成需要回调的 API,这样参数更少。示例 5-26 做了简单的演示。
      示例 5-26 使用 partial 把一个两参数函数改编成需要单参数的 可调用对象
    >>> from operator import mul
    >>> from functools import partial
    >>> triple = partial(mul, 3) ➊
    >>> triple(7) ➋
    21
    >>> list(map(triple, range(1, 10))) ➌
    [3, 6, 9, 12, 15, 18, 21, 24, 27]
    ➊ 使用 mul 创建 triple 函数,把第一个定位参数定为 3。
    ➋ 测试 triple 函数。
    ➌ 在 map 中使用 triple;在这个示例中不能使用 mul。
     
    人生就是要不断折腾
  • 相关阅读:
    leetcode5 Longest Palindromic Substring
    leetcode17 Letter Combinations of a Phone Number
    leetcode13 Roman to Integer
    leetcode14 Longest Common Prefix
    leetcode20 Valid Parentheses
    leetcode392 Is Subsequence
    leetcode121 Best Time to Buy and Sell Stock
    leetcode198 House Robber
    leetcode746 Min Cost Climbing Stairs
    tomcat下使用druid配置jnid数据源
  • 原文地址:https://www.cnblogs.com/xiangxiaolin/p/11609324.html
Copyright © 2011-2022 走看看