【问题标题】:Efficient way to preserve object type after a slicing operation切片操作后保留对象类型的有效方法
【发布时间】:2015-06-25 12:34:54
【问题描述】:

我正在寻找一种快速、干净和 Pythonic 的方式来切片定制对象,同时在操作后保留它们的类型。

为了给您一些背景信息,我必须处理大量半非结构化数据并使用字典列表来处理它们。为了简化一些操作,我创建了一个继承自“list”的“ld”对象。在其众多功能中,它检查数据是否以正确的格式提供。让我们通过说它确保列表的所有条目都是包含一些键“a”的字典来简化它,如下所示:

class ld( list):
     def __init__(self, x):
          list.__init__(self, x)
          self.__init_check()

     def __init_check(self):
          for record in self:
               if isinstance( record, dict) and "a" in record:
                    pass
               else:
                     raise TypeError("not all entries are dictionaries or have the key 'a'")
          return

当数据符合要求并初始化 ld 时,此行为正确:

tt = ld( [{"a": 1, "b":2}, {"a":4}, {"a":6, "c":67}])
type( tt)

当数据不正确时,它也是正确的:

ld( [{"w":1}])
ld( [1,2,3])

但是,当我继续对对象进行切片时,问题就来了:

type( tt[:2])

tt[:2] 是一个列表,不再是我在成熟的 ld 对象中创建的所有方法和属性。我可以将切片重新转换为 ld,但这意味着它必须再次经历整个初始数据检查过程,从而大大降低了计算速度。

这是我想出的加快速度的解决方案:

class ld( list):
    def __init__(self, x, safe=True):
        list.__init__(self, x)
        self.__init_check( safe)

    def __init_check(self, is_safe):
        if not is_safe:
            return
        for record in self:
            if isinstance( record, dict) and "a" in record:
                pass
            else:
                raise TypeError("not all entries are dictionaries or have the key 'a'")
        return

    def __getslice__(self, i, j):
        return ld( list.__getslice__( self, i, j), safe=False)

有没有一种更简洁、更 Pythonic 的方式来处理它? 提前感谢您的帮助。

【问题讨论】:

    标签: python performance oop casting slice


    【解决方案1】:

    我不认为继承list 来验证其内容的形状或类型通常是正确的方法。 list 明确地不关心它的内容,并且实现一个构造函数行为根据传递给它的标志而变化的类是混乱的。如果您需要一个验证输入的构造函数,只需在返回列表的函数中执行检查逻辑即可。

    def make_verified_list(items):
        """
        :type items: list[object]
        :rtype: list[dict]
        """
        new_list = []
        for item in items:
            if not verify_item(item):
                 raise InvalidItemError(item)
            new_list.append(item)
        return new_list
    
    def verify_item(item):
        """
        :type item: object
        :rtype: bool
        """
        return isinstance(item, dict) and "a" in item
    

    采用这种方法,您不会发现自己在为核心数据结构的行为而苦恼。

    【讨论】:

    • 感谢您的建议,但该对象执行与问题无关的多项任务,因此我跳过了它们。对我来说,问题的核心是维护对象类型。
    猜你喜欢
    • 1970-01-01
    • 2012-11-25
    • 2011-04-24
    • 2016-03-15
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    相关资源
    最近更新 更多