美文网首页
Python3实现插入即更新列表,存在更新不存在插入新值

Python3实现插入即更新列表,存在更新不存在插入新值

作者: SystemLight | 来源:发表于2020-05-31 15:22 被阅读0次

    简单使用案例一

    注意:UpdateList核心代码放到了文章最底部

    # 举例一:最简单的使用方式,UpdateList提供四个钩子回调可以灵活自定义各种使用方式
    box = UpdateList([{"key": "1", "count": 1}, {"key": "2", "count": 1}, {"key": "3", "count": 1}])
    print(box[1])  # 输出:{'key': '2', 'count': 1},默认情况和list没有区别
    
    box.key = "key"  # 为UpdateList定义对象key值,之后查询和设置都将通过子项key进行操作
    print(box['2'])  # 输出:(1, {'count': 1, 'key': '2'})  元组(索引值,对象内容)
    
    
    # 使用update方法之前必须定义on_update事件回调
    def on_update(old, new):
        old["count"] += new["count"]
        return old
    
    
    box.on_update = on_update
    box.update({"key": "2", "count": 12})
    box.update({"key": "5", "count": 1})
    print(box)
    # 输出:[{'key': '1', 'count': 1}, {'key': '2', 'count': 13}, {'key': '3', 'count': 1}, {'key': '5', 'count': 1}]
    # 插入一个新内容,更新一个旧内容
    

    复杂使用案例二

    根据坐标进行区间索引,动态生成扩张区域并通过UpdateList更新或插入

    def extension(position):
        """
    
        扩张坐标区域
    
        :param position: 位置系数
        :return: 拓张区域范围值
    
        """
        return position - 10, position + 10
    
    
    def on_key(val, key):
        """
    
        当前val值,key值
    
        :param val:
        :param key:
        :return:
    
        """
        return val["max"] > key > val["min"]
    
    
    def on_fetch_key(item):
        """
    
        传入一个item返回key值
    
        :param item:
        :return:
    
        """
        return item["x"]
    
    
    def on_update(old, new):
        """
    
        定义如何更新数据
    
        :param old: 旧数据
        :param new: 新数据
        :return: 更新的数据
    
        """
        old["item"].append(new)
        return old
    
    
    def on_append(val):
        """
    
        自定义如何增加数据格式
    
        :param val: 传入数据格式
        :return: 添加数据
    
        """
        mi, ma = extension(val["x"])
        return {"min": mi, "max": ma, "item": []}
    
    
    box = UpdateList([])
    # box.key = "key"
    box.key = on_key
    box.on_fetch_key = on_fetch_key
    box.on_update = on_update
    box.on_append = on_append
    
    box.update({"x": 6})
    box.update({"x": 7})
    box.update({"x": 8})
    
    box.update({"x": 125})
    box.update({"x": 126})
    box.update({"x": 127})
    
    print(box)
    

    UpdateList类型核心代码

    class UpdateList(list):
        """
    
        主要方法update(),该方法是对list类型拓展,
        当update的数据对象存在时对其更新,注意请保证UpdateList
        的子项是dict类型而不要使用值类型,值类型对于UpdateList毫无意义
    
        on_update hook函数,接收old_val(旧数据), p_object(新数据),需要返回更新数据
        on_append hook函数,接收p_object(添加数据),需要返回添加数据
        on_fetch_key hook函数,当key属性定义为函数时需要同时定义如何捕获key值
    
        key 支持字符串,字符串指定子元素中的更新参考值
            支持函数,接收val(当前数据),key(参考key值)该key值由on_fetch_key返回,函数返回bool值True为更新,False为添加
    
        on_fetch_key作用::
    
            复杂场景下我们可能需要up[("home2", True)]这样来找到响应的item,这样显示传递key值没有什么问题,key函数可以获取到
            相应的key数据以供我们处理,但是当我们调用update时,update需要判断该内容是更新还是添加,这时我们传入的内容是数据,显然
            update无法知晓如何获取我们想要的类型key值,如("home2", True),所以我们要定义on_fetch_key来告知update如何捕获我们
            想要的类型的key值,on_fetch_key只有当key属性定义为函数时才有意义。
    
        """
    
        def __init__(self, *args, **kwargs):
            super(UpdateList, self).__init__(*args, **kwargs)
    
            # 对象key值,可以是函数,函数接收val, key返回布尔值代表满足条件
            self.key = None
            # 当key设置为函数时必须定义的回调,传入item对象返回该对象key值内容
            self.on_fetch_key = None
            # 当元素是更新时调用的更新方法,如果元素是插入时不调用,如果不定义该回调默认直接替换
            self.on_update = None
            # 当元素update方法触发的是添加时调用的回调函数,可以自定义append类型
            self.on_append = None
    
        def __getitem__(self, key):
            if isinstance(self.key, str):
                return self.find(lambda val: val[self.key] == key)
            elif hasattr(self.key, "__call__"):
                return self.find(lambda val: self.key(val, key))
            else:
                return super(UpdateList, self).__getitem__(key)
    
        def __setitem__(self, key, value):
            if isinstance(self.key, str):
                key = self.find(lambda val: val[self.key] == key)[0]
            elif hasattr(self.key, "__call__"):
                key = self.find(lambda val: self.key(val, key))[0]
            super(UpdateList, self).__setitem__(key, value)
    
        def update(self, p_object):
            """
    
            类似于append方法,不同的是当内容存在时会对内容进行更新,更新逻辑遵从update_callback
            而当内容不存在时与append方法一致进行末尾加入内容
    
            :param p_object: 内容对象
            :return: None
    
            """
            if not self.on_update:
                self.on_update = lambda o, p: p
    
            old_val = None
            if isinstance(self.key, str):
                key = p_object.get(self.key) or -1
                if key != -1:
                    key, old_val = self.find(lambda val: val[self.key] == key)
            elif hasattr(self.key, "__call__"):
                try:
                    key, old_val = self.find(lambda val: self.key(val, self.on_fetch_key(p_object)))
                except TypeError:
                    raise TypeError("Function `on_fetch_key` is not defined")
            else:
                raise TypeError("`key` is TypeError")
    
            if key == -1:
                if self.on_append:
                    self.append(self.on_append(p_object))
                else:
                    self.append(p_object)
            else:
                super(UpdateList, self).__setitem__(key, self.on_update(old_val, p_object))
    
        def find(self, callback):
            """
    
            返回满足回调函数的内容
    
            :param callback: 回调函数,返回布尔类型用于判断是否满足要求
            :return: (索引,值)
    
            """
            for index, item in enumerate(self):
                if callback(item):
                    return index, item
            return -1, None
    

    相关文章

      网友评论

          本文标题:Python3实现插入即更新列表,存在更新不存在插入新值

          本文链接:https://www.haomeiwen.com/subject/vstrzhtx.html