如何使用元组和字典特征的数据结构

时间:2010-11-10 08:12:12

标签: python psycopg2

参考

的代码

http://initd.org/psycopg/docs/extras.html#dictionary-like-cursor

>>> rec['data']
"abc'def"
>>> rec[2]
"abc'def"

我想知道他们是如何设法创建具有元组和字典特征的数据结构的?

6 个答案:

答案 0 :(得分:5)

在Python中,[]查找由__getitem__魔术方法处理;换句话说,当您索引自定义类时,Python将调用instance.__getitem__(...)并返回值。这可以让你做到。

>>> class Foo:
...     def __getitem__(self, value):
...             return value
...
>>> foo = Foo()
>>> foo["1"]
'1'
>>> foo[0]
0

有几种自然的方式来维护实际的数据结构;可能最简单的方法是根据键的类型将两个 dict以及列表和索引保存到其中一个中。

请注意,这是不自然的;你会期望一个类似dict的对象将0视为关键。可能值得写一种不同的方法,例如index来处理索引。

您可能还希望实施__setitem____contains__方法。

答案 1 :(得分:2)

以下是demas的答案的修改版本(我认为)将保留排序(但效率不高):

class TupleDict(collections.OrderedDict):

    def __getitem__(self, key):
       if isinstance(key, int):
           return list(self.values())[key]
       return super(TupleDict, self).__getitem__(key)

答案 2 :(得分:1)

阅读代码。这是我最好的建议。

例如:

class cursor(_2cursor):
    """psycopg 1.1.x cursor.

    Note that this cursor implements the exact procedure used by psycopg 1 to
    build dictionaries out of result rows. The DictCursor in the
    psycopg.extras modules implements a much better and faster algorithm.
    """

    def __build_dict(self, row):
        res = {}
        for i in range(len(self.description)):
            res[self.description[i][0]] = row[i]
        return res
    .....

它来自哪里..

class connection(_2connection):
    """psycopg 1.1.x connection."""

    def cursor(self):
        """cursor() -> new psycopg 1.1.x compatible cursor object"""
        return _2connection.cursor(self, cursor_factory=cursor)

答案 3 :(得分:1)

在阅读了Glenn Maynard关于导致我删除这个的答案的评论后,我决定复活它。这使用普通列表来存储索引,因此将具有相同的O(1)访问权限。


这是我的看法。错误处理可能会有所改进,但我不想过多地混淆代码。我不知道原始代码如何处理它,但为什么不继续处理切片。我们只能处理不创建新键的切片的切片分配(也就是说,不会改变项的数量)但我们可以处理任意切片查找。请注意,它也有效地禁止整数键。这是它的small demo

class IndexedDict(object):
    def __init__(self, *args, **kwargs):
        d = dict(*args, **kwargs)
        self._keys = d.keys() # list(d.keys()) in python 3.1
        self._d = d

    def __getitem__(self, item):
        if isinstance(item, int):
            key = self._keys[item]
            return self._d[key]
        elif isinstance(item, slice):
            keys = self._keys[item]
            return tuple(self._d[key] for key in keys)
        else:
            return self._d[key]

    def __setitem__(self, item, value):
        if isinstance(item, int):
            key = self._keys[item]
            self._d[key] = value
        elif isinstance(item, slice):
            # we only handle slices that don't require the creation of
            # new keys.
            keys = self._keys[item]
            if not len(keys) == len(value):
                raise ValueError("Complain here")
            for key, v in zip(keys, value):
                self._d[key] = v
        else:
            self._d[item] = value
            if item not in self._keys:
                # This is the only form that can create a new element
                self._keys.append(item)


    def __delitem__(self, item):
        if isinstance(item, int):
            key = self._keys[item]
            del self._keys[item]
            del self._d[key]
        elif isinstance(item, slice):
            keys = self._keys[item]
            del self._keys[item]
            for key in keys:
                del self._d[key]
        else:
            del self._d[item]
            self._keys.remove(item)

    def __contains__(self, item):
        if isinstance(item, int):
            return i < len(self._keys)
        else:
            return i in self._d

    # Just for debugging. Not intended as part of API.
    def assertions(self):
        assert len(self._d) == len(self._keys)
        assert set(self._d.keys()) == set(self._keys)

还有一些东西需要实施。 keysitemsiteritemsupdate等,但它们不应该太难。只需使用self._keys并使用list comps和generator表达式。例如,iteritems只是(self._d[key] for key in self._keys)对于更新,我只是确保您正在处理类似于dict的对象,然后将self._keys更新为self._keys += [key for key in other.keys() if key not in self._keys]。我可能会以基本相同的方式定义__add__

答案 4 :(得分:0)

字典可以将任何python类型映射到任何其他python类型,因此检索键是整数的值很简单。

v = {}
v[0] = 'a'
v[1] = 'b'
v['abc'] = 'def'

>>> v[0]
'a'

答案 5 :(得分:0)

类似的东西:

class d(dict):
    def __getitem__(self, key):
       if str(key).isdigit():
           return self.values()[key]
       else:
           return super(d, self).get(key)

cls = d()
cls["one"] = 1
print cls["one"]
print cls[0]