如何在扩展 dict 时正确覆盖方法 keys()(在 python3 中)
How to properly override method keys() while extending dict (in python3)
编辑:我添加了 class 和一些信息,请参阅新的 post。
我创建了一个扩展 dict
和 set
的 class(更准确地说,我扩展了 collections.abc.MutableMapping
和 MutableSet
)。现在我想正确地覆盖方法 keys()
.
这个class表示一组其他对象,称为Measurand
:
class Measurands(MutableSet, MutableMapping):
@property
def measurands(self):
return self._measurands
@measurands.setter
def measurands(self, val):
self._measurands = []
for el in val:
self.add(el)
def __init__(self, arg=None):
if arg is None:
self.measurands = []
else:
try:
measurands = arg.measurands
except AttributeError:
if isinstance(arg, Iterable):
measurands = list(arg)
else:
measurands = [arg]
self.measurands = measurands
def __iter__(self):
return iter(self.measurands)
def __getitem__(self, key):
for m in self:
if m.id == key:
return m
raise KeyError(key)
def __contains__(self, el_x):
is_in = False
for el in self:
if el_x.id == el.id:
is_in = True
break
return is_in
def add(self, el):
try:
self[el.id].session_ids |= el.session_ids
except KeyError:
self[el.id] = Measurand(el)
def _discard(self, key):
res = False
for i, m in enumerate(self):
if m.id == key:
del self.measurands[i]
res = True
break
return res
def __delitem__(self, key):
res = self._discard(self, key)
if not res:
raise KeyError(key)
def discard(self, key):
self._discard(self, key)
def remove(self, key):
self.__delitem__(self, key)
def __len__(self):
return len(self.measurands)
def __setitem__(self, key, value):
res = False
value_true = Measurand(value)
for i, m in enumerate(self):
if m.id == key:
res = True
if value.id == key:
self.measurands[i] = value_true
else:
raise KeyError(key)
break
if not res:
self.measurands.append(value_true)
def __str__(self):
string = "Measurands({"
for m in self:
string += str(m)
string += ", "
if string:
string = string[:-2]
string += "})"
return string
问题是默认方法 keys
return 是 Measurand
对象的“列表”。这不是我想要的。键应该是 Measurand
个对象的 属性 id
。
目前我正在 return 创建一个简单的 list
,但我会 return dict_keys
或 collection.abc.KeysView
对象。不幸的是,dict_keys
不是全局名称。
dict_keys
在哪里?
- 这是correct/pythonic的方法吗?
我还没有找到任何方法将某些东西转换为 dict_keys
类型,但是在阅读了介绍访问键和值的新方法的 PEP (PEP 3106) 之后, dict_keys
似乎被介绍给了
return a set-like or unordered container object whose contents are derived from the underlying dictionary rather than a list which is a copy of the keys, etc.
考虑到这一点,看起来您可以使用 keys()
方法而不是列表返回生成器对象。
这是来自 PEP 的伪代码:
class dict:
# Omitting all other dict methods for brevity.
def keys(self):
return d_keys(self)
class d_keys:
def __init__(self, d):
self.__d = d
def __len__(self):
return len(self.__d)
def __contains__(self, key):
return key in self.__d
def __iter__(self):
for key in self.__d:
yield key
Python3 文档说 dict.keys()
return 值类型(即视图)是 "set-like",因此您的 return 值应该是 "set-like" 还有。
The objects returned by dict.keys(), dict.values() and dict.items()
are view objects. They provide a dynamic view on the dictionary’s
entries, which means that when the dictionary changes, the view
reflects these changes.
Dictionary views can be iterated over to yield their
respective data, and support membership tests:
....
Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).
全文在这里:
https://docs.python.org/3/library/stdtypes.html#dict-views
这已经为您处理好了! collections.abc.MutableMapping
包含 keys
的合理默认实现,它提供与 dict.keys
.
相同的接口
只需删除您的 keys
方法,您将使用继承的实现。
编辑:我添加了 class 和一些信息,请参阅新的 post。
我创建了一个扩展 dict
和 set
的 class(更准确地说,我扩展了 collections.abc.MutableMapping
和 MutableSet
)。现在我想正确地覆盖方法 keys()
.
这个class表示一组其他对象,称为Measurand
:
class Measurands(MutableSet, MutableMapping):
@property
def measurands(self):
return self._measurands
@measurands.setter
def measurands(self, val):
self._measurands = []
for el in val:
self.add(el)
def __init__(self, arg=None):
if arg is None:
self.measurands = []
else:
try:
measurands = arg.measurands
except AttributeError:
if isinstance(arg, Iterable):
measurands = list(arg)
else:
measurands = [arg]
self.measurands = measurands
def __iter__(self):
return iter(self.measurands)
def __getitem__(self, key):
for m in self:
if m.id == key:
return m
raise KeyError(key)
def __contains__(self, el_x):
is_in = False
for el in self:
if el_x.id == el.id:
is_in = True
break
return is_in
def add(self, el):
try:
self[el.id].session_ids |= el.session_ids
except KeyError:
self[el.id] = Measurand(el)
def _discard(self, key):
res = False
for i, m in enumerate(self):
if m.id == key:
del self.measurands[i]
res = True
break
return res
def __delitem__(self, key):
res = self._discard(self, key)
if not res:
raise KeyError(key)
def discard(self, key):
self._discard(self, key)
def remove(self, key):
self.__delitem__(self, key)
def __len__(self):
return len(self.measurands)
def __setitem__(self, key, value):
res = False
value_true = Measurand(value)
for i, m in enumerate(self):
if m.id == key:
res = True
if value.id == key:
self.measurands[i] = value_true
else:
raise KeyError(key)
break
if not res:
self.measurands.append(value_true)
def __str__(self):
string = "Measurands({"
for m in self:
string += str(m)
string += ", "
if string:
string = string[:-2]
string += "})"
return string
问题是默认方法 keys
return 是 Measurand
对象的“列表”。这不是我想要的。键应该是 Measurand
个对象的 属性 id
。
目前我正在 return 创建一个简单的 list
,但我会 return dict_keys
或 collection.abc.KeysView
对象。不幸的是,dict_keys
不是全局名称。
dict_keys
在哪里?- 这是correct/pythonic的方法吗?
我还没有找到任何方法将某些东西转换为 dict_keys
类型,但是在阅读了介绍访问键和值的新方法的 PEP (PEP 3106) 之后, dict_keys
似乎被介绍给了
return a set-like or unordered container object whose contents are derived from the underlying dictionary rather than a list which is a copy of the keys, etc.
考虑到这一点,看起来您可以使用 keys()
方法而不是列表返回生成器对象。
这是来自 PEP 的伪代码:
class dict:
# Omitting all other dict methods for brevity.
def keys(self):
return d_keys(self)
class d_keys:
def __init__(self, d):
self.__d = d
def __len__(self):
return len(self.__d)
def __contains__(self, key):
return key in self.__d
def __iter__(self):
for key in self.__d:
yield key
Python3 文档说 dict.keys()
return 值类型(即视图)是 "set-like",因此您的 return 值应该是 "set-like" 还有。
The objects returned by dict.keys(), dict.values() and dict.items() are view objects. They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.
Dictionary views can be iterated over to yield their respective data, and support membership tests:
....
Keys views are set-like since their entries are unique and hashable. If all values are hashable, so that (key, value) pairs are unique and hashable, then the items view is also set-like. (Values views are not treated as set-like since the entries are generally not unique.) For set-like views, all of the operations defined for the abstract base class collections.abc.Set are available (for example, ==, <, or ^).
全文在这里: https://docs.python.org/3/library/stdtypes.html#dict-views
这已经为您处理好了! collections.abc.MutableMapping
包含 keys
的合理默认实现,它提供与 dict.keys
.
只需删除您的 keys
方法,您将使用继承的实现。