通过参考代码
http://initd.org/psycopg/docs/extras.html#dictionary-like-cursor
>>> rec['data']
"abc'def"
>>> rec[2]
"abc'def"
我想知道他们如何设法制作具有元组和字典特征的数据结构?
通过参考代码
http://initd.org/psycopg/docs/extras.html#dictionary-like-cursor
>>> rec['data']
"abc'def"
>>> rec[2]
"abc'def"
我想知道他们如何设法制作具有元组和字典特征的数据结构?
在 Python 中,[]
查找由__getitem__
魔术方法处理;换句话说,当您索引自定义类时,Python 将调用instance.__getitem__(...)
并返回值。这可以让你做例如
>>> class Foo:
... def __getitem__(self, value):
... return value
...
>>> foo = Foo()
>>> foo["1"]
'1'
>>> foo[0]
0
有几种维护实际数据结构的自然方式;可能最简单的方法是同时维护一个字典和一个列表,并根据键的类型对其中一个进行索引。
请注意,这是不自然的;您会期望类似 dict 的对象被0
视为键。可能值得编写不同的方法,例如index
处理索引。
您可能还希望实现__setitem__
和__contains__
方法。
这是demas答案的修改版本,(我认为)将保留排序(但不会有效):
class TupleDict(collections.OrderedDict):
def __getitem__(self, key):
if isinstance(key, int):
return list(self.values())[key]
return super(TupleDict, self).__getitem__(key)
阅读代码。这是我最好的建议。
例如:
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)
在阅读了 Glenn Maynard 对导致我删除这个答案的答案的评论后,我决定复活它。这使用普通列表来存储索引,因此将具有相同的 O(1) 访问权限。
这是我的看法。错误处理可能会得到改进,但我不想过多地混淆代码。我不知道原始代码是如何处理它的,但为什么不继续处理切片。我们只能处理不创建新键(即不改变项目数)的切片的切片分配,但我们可以处理任意切片查找。请注意,它也有效地禁止整数键。这是它的一个小演示。
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)
还有一些东西要实施。keys
, items
, iteritems
, update
, 等等,但它们不应该太难。只需self._keys
使用列表组合和生成器表达式即可。例如,iteritems
只是(self._d[key] for key in self._keys)
为了更新,我会确保你正在处理一个 dictlike 对象,然后更新self._keys
为self._keys += [key for key in other.keys() if key not in self._keys]
. 我可能会以__add__
基本相同的方式定义。
字典可以将任何 python 类型映射到任何其他 python 类型,因此检索键为整数的值很简单。
v = {}
v[0] = 'a'
v[1] = 'b'
v['abc'] = 'def'
>>> v[0]
'a'
像这样的东西:
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]