更新问题:在Python中,我可以创建一个自定义的数据结构dict
,但是我可以将其获取并设置为set
,并且可以为其创建自定义的__str__
表示吗?
我想要一个class属性,它在结构上是一个dict{str:list[str]},但用户界面(因为缺乏更好的词)将其视为一个set[str]。而且我想打印它像一个字典与自定义格式。
尝试解决方案:我实现了一个Descriptor,但我还没有弄清楚如何自定义__str__
,所以我认为Descriptor实际上不是我应该尝试的。
class TreatDictLikeSet(): # The Descriptor I wish existed
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, type=None) -> object:
my_dict = obj.__dict__.get(self.name) or {}
return [e for v in my_dict.values() for e in v]
def __set__(self, obj, value) -> None:
value = ...<rules to insert set values into a dict>...
obj.__dict__[self.name] = value
class Foo():
my_dict = TreatDictLikeSet()
1条答案
按热度按时间uyhoqukh1#
如果您想要的只是行为 “assign
set
,but getdict
“,我不确定您是否需要处理描述符。看起来简单的
property
就可以了:更新
如果你想要一个行为像标准集合类的东西(例如a
set
),一个好的起点通常是collections.abc
模块。例如,你可以子类化
MutableSet
,实现它的抽象方法(__contains__
、__iter__
、__len__
、add
和discard
),还可以为它实现你自己的__init__
**和__str__
**方法:如您所愿,底层数据结构是一个列表字典。我只是实现了一些任意的规则来创建字典键,以用于演示目的。
正如@ Blckknight在评论中指出的那样,您在下面使用不同的数据结构意味着操作的运行时可能会非常不同。具体来说,正如你所看到的,我在这里实现
__contains__
的方式是 O(n),而不是实际集合的 O(1)。这是因为我循环遍历dict
的整个values
视图来查找某个值,而不是像使用集合那样进行散列和查找。另一方面,即使删除原则上同样昂贵,由于
dict
键逻辑的 * 这个特定 * 实现,删除(discard
)也同样有效,因为值是键的一部分。当然,你也可以将这些值存储在字典旁边的一个 actual set中,这样可以再次提高这些操作的效率,但是这显然会为每个值占用两倍的内存。
无论哪种方式,你现在都可以将这个类作为一个常规的(可变的)集合来使用,但是它的字符串表示是底层字典的字符串表示:
现在,如果您出于某种原因仍然需要描述符魔法,您可以编写一个在后台使用此类的描述符,即。在它的
__set__
中初始化一个新对象,并在它的__get__
方法中返回它:然后这样使用: