zoukankan      html  css  js  c++  java
  • Python 中的一些小技巧

    这里是本人收集的一些 Python 小技巧,目前主要是一些实用函数,适合有一定基础的童鞋观看(不会专门介绍使用到的标准库函数)。。

    一、函数式编程

    函数式编程用来处理数据,感觉很方便。(要是再配上管道操作符 | 或者 Java 的那种链式调用,超级爽!可惜 Python 都没有。。需要借助第三方库)

    1. 分组/group

    数据处理中一个常见的操作,是将列表中的元素,依次每 k 个分作一组。

    def group_each(a, size: int):
        """
            将一个可迭代对象 a 内的元素, 每 size 个分为一组
            group_each([1,2,3,4], 2) -> [(1,2), (3,4)]
        """
        iterators = [iter(a)] * size  # 将新构造的 iterator 复制 size 次(浅复制)
        return zip(*iterators)  # 然后 zip
    

    这个函数之前在 Python 拾遗 - 奇技淫巧 中就写过,记得是某次 Google 时在 stackoverflow 上发现的,不过它的最初来源应该是 Python 官方文档的某个角落。

    顺便如果某个 size 比较常用(比如 2),还可以用 partial 封装一下

    from functools import partial
    
     # 每两个分一组
    group_each_2 = partial(group_each, size=2)  # 等同于 group_each_2 = lambda a: group_each(a, 2)
    

    2. 扁平版本的 map

    稍微接触过函数式应该都知道 flat_map,可 Python 标准库却没有提供。下面是我在 stackoverflow 上找到的实现,其实很简单

    from itertools import chain
    
    def flat_map(f, items):
        return chain.from_iterable(map(f, items))
    

    它和 map 的差别在于是不是扁平(flat) 的(废话。。),举个例子

    >>> list(map(list, ['123', '456']))
    [['1', '2', '3'], ['4', '5', '6']]
    >>> list(flat_map(list, ['123', '456']))
    ['1', '2', '3', '4', '5', '6']
    

    3. 轮流迭代多个迭代器

    假设我有多个可迭代对象(迭代器、列表等),现在我需要每次从每个对象中取一个值,直到某个对象为空。如果用循环写会比较繁琐,但是用 itertools 可以这样写:

    from itertools import chain
    
    def iter_one_by_one(items):
        return chain.from_iterable(zip(*items))
    

    n sum(x)

    
    ### 4. 上述函数的应用举例
    
    在做爬虫工作时,有时会遇到这样的 table 元素:
    ![](https://images2018.cnblogs.com/blog/968138/201809/968138-20180908192708616-1521425251.png)
    
    对这种 html 元素,我一般会直接把它转换成 list,结果如下:
    ```python3
    table = [['label1', 'value1', 'label2', 'value2'],
             ['label3', 'value3'],
             ['label4', 'value4', 'label5', 'value5'],
             ...
             ]
    

    为了方便索引,现在我需要把上面的数据转换成下面这个样子的 dict

    {
        'label1': 'value1',
        'label2': 'value2',
        'label3': 'value3',
        'label4': 'value4',
        'label5': 'value5'
    }
    

    如果是平常,大概需要写循环了。不过如果用刚刚说到的几个函数的话,会变得异常简单

     # 1. 分组
    groups = flat_map(group_each_2, table)
    
    # 1.1 flat_map 返回的是迭代器,list 后内容如下:
    # [('label1', 'value1'),
    #  ('label2', 'value2'),
    #  ('label3', 'value3'),
    #  ('label4', 'value4'),
    #  ('label5', 'value5')]
    
    # 2. 转换成 dict
    key_values = dict(groups)   # 得到的 key_values 与上面需要的 dict 别无二致。
    

    二、其他

    1. 多 dict 的去重

    假设我们有一个 dict 的列表,里面可能有内容一模一样的 dict,我们需要对它做去重。
    容易想到的方法就是使用 set,可是 set 中的元素必须是 hashable 的,而 dict 是 unhashable 的,因此不能直接放进 set 里。

    >>> a = [{'a': 1}, {'a': 1}, {'b': 2}]
    >>> set(a)
    Traceback (most recent call last):
      File "/usr/local/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 2961, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "<ipython-input-5-5b4c643a6feb>", line 1, in <module>
        set(a)
    TypeError: unhashable type: 'dict'
    

    难道就必须手写递归了么?未必,我在 stackoverflow 看到这样一个小技巧

    import json
    
    def unique_dicts(data_list: list):
        """unique a list of dict
            dict 是 unhashable 的,不能放入 set 中,所以先转换成 str
            
            unique_dicts([{'a': 1}, {'a': 1}, {'b': 2}])  ->  [{'a': 1}, {'b': 2}]
        """
        data_json_set = set(json.dumps(item) for item in data_list)
        return [json.loads(item) for item in data_json_set]
    

    2. str 的 startswith 和 endswith 两个函数的参数可以是元组

    In[7]: a = "bb.gif"
    In[8]: b = 'a.jpg'
    In[9]: a.endswith(('.jpg', '.gif'))
    Out[9]: True
    In[10]: b.startswith(('bb', 'a'))
    Out[10]: True
    

    3. 判断两个对象的所有属性都相同

    python 和 java 一样,直接用 == 做判断,默认是比较的引用,相当于 is。对自定义的类,你需要重写 __eq__ 函数。
    判断值相等的方法很简单,一行代码:

    class A:
        ...
        def __eq__(self, obj):
            return self.__dict__ == obj.__dict__  # 转成 __dict__ 再比较
    

    设计模式

    我曾经写过一个 QQ 机器人,它需要根据不同的命令,来干不同的事。

    最初的做法,是直接用 if-else 判断。然后慢慢的,我的项目的 if-else 就越来越长,变得惨不忍睹了。。

    这个地方要重构,我网上搜了下,有人说 if-else 用 dict 重构就好了,但是那只适用于 switch value 模式,就是只是单纯检查 value 的值 match 与否。
    而我的 QQ 机器人的检查条件要更复杂。

    然后今天突然想到,可以用 正则 做 key,用 function 做 value,并且使用 orderdict。然后直接遍历。

    参考

    慢慢更新,想到啥就加啥。

    本文允许转载,但要求附上源地址 https://www.cnblogs.com/kirito-c/p/9610179.html

  • 相关阅读:
    How to alter department in PMS system
    Can't create new folder in windows7
    calculate fraction by oracle
    Long Wei information technology development Limited by Share Ltd interview summary.
    ORACLE BACKUP AND RECOVERY
    DESCRIBE:When you mouse click right-side is open an application and click left-side is attribution.
    ORACLE_TO_CHAR Function
    电脑BOIS设置
    JSP点击表头排序
    jsp+js实现可排序表格
  • 原文地址:https://www.cnblogs.com/kirito-c/p/9610179.html
Copyright © 2011-2022 走看看