python - 转换为一组自定义集合类在 Python 中返回空集

标签 python collections set

我最近编写了自己的 OrderedSet 实现,因为我在公开可用的有序/排序集实现方面遇到了问题。该类在后台使用 dict 代理对象,主要是转发操作。我实现了所有(在我看来)相关的方法,包括。 __iter__,并且像 list(myset) 这样的调用按预期工作。

但是,调用 set(myset) 总是 返回空集。

这是 OrderedSet 的完整代码:

from typing import TypeVar, Generic, Optional, Iterable, Set, AbstractSet, Union, Iterator, Any, Dict

T = TypeVar("T")
S = TypeVar("S")


class OrderedSet(Generic[T], Set[T]):
    def __init__(self, base: Optional[Union[Dict[T, None], Iterable[T]]] = None):
        super().__init__()

        self.the_dict: Dict[T, None]
        if not base:
            self.the_dict = {}
        elif isinstance(base, dict):
            self.the_dict = base
        else:
            self.the_dict = dict.fromkeys(base)

    def __eq__(self, o: object) -> bool:
        return isinstance(o, OrderedSet) and list(self.the_dict) == list(o.the_dict)

    def __ne__(self, o: object) -> bool:
        return not self.__eq__(o)

    def __str__(self) -> str:
        return "{" + ", ".join(list(map(str, self.the_dict))) + "}"

    def __repr__(self) -> str:
        return f"OrderedSet({repr(self.the_dict)})"

    def add(self, element: T) -> None:
        self.the_dict = {**self.the_dict, **{element: None}}

    def clear(self) -> None:
        self.the_dict.clear()

    def copy(self) -> 'OrderedSet[T]':
        return OrderedSet(self.the_dict.copy())

    def difference(self, s: Iterable[Any]) -> 'OrderedSet[T]':
        return OrderedSet({e: None for e in self.the_dict if e not in s})

    def difference_update(self, s: Iterable[Any]) -> None:
        self.the_dict = {e: None for e in self.the_dict if e not in s}

    def discard(self, element: T) -> None:
        del self.the_dict[element]

    def intersection(self, s: Iterable[Any]) -> 'OrderedSet[T]':
        return OrderedSet({e: None for e in self.the_dict if e in s})

    def intersection_update(self, s: Iterable[Any]) -> None:
        self.the_dict = {e: None for e in self.the_dict if e in s}

    def isdisjoint(self, s: Iterable[Any]) -> bool:
        return self.the_dict.keys().isdisjoint(s)

    def issubset(self, s: Iterable[Any]) -> bool:
        return set(iter(self)).issubset(iter(s))

    def issuperset(self, s: Iterable[Any]) -> bool:
        return set(iter(self)).issuperset(iter(s))

    def pop(self) -> T:
        items = list(self.the_dict)
        result = items.pop()
        self.the_dict = dict.fromkeys(items)
        return result

    def remove(self, element: T) -> None:
        del self.the_dict[element]

    def symmetric_difference(self, s: Iterable[T]) -> 'OrderedSet[T]':
        return OrderedSet(
            dict.fromkeys([e for e in self.the_dict if e not in s] +
                          [e for e in s if e not in self.the_dict]))

    def symmetric_difference_update(self, s: Iterable[T]) -> None:
        self.the_dict = self.symmetric_difference(s).the_dict

    def union(self, s: Iterable[T]) -> 'OrderedSet[T]':
        return OrderedSet({**self.the_dict, **dict.fromkeys(s)})

    def update(self, s: Iterable[T]) -> None:
        self.the_dict = self.union(s).the_dict

    def __len__(self) -> int:
        return len(self.the_dict)

    def __contains__(self, o: object) -> bool:
        return o in self.the_dict

    def __iter__(self) -> Iterator[T]:
        return iter(self.the_dict)

    def __and__(self, s: AbstractSet[object]) -> 'OrderedSet[T]':
        return self.intersection(s)

    def __iand__(self, s: AbstractSet[object]) -> 'OrderedSet[T]':
        result = self.intersection(s)
        self.the_dict = result.the_dict
        return result

    def __or__(self, s: AbstractSet[S]) -> 'OrderedSet[Union[T, S]]':
        return self.union(s)

    def __ior__(self, s: AbstractSet[S]) -> 'OrderedSet[Union[T, S]]':
        result = self.union(s)
        self.the_dict = result.the_dict
        return result

    def __sub__(self, s: AbstractSet[Optional[T]]) -> 'OrderedSet[T]':
        return self.difference(s)

    def __isub__(self, s: AbstractSet[Optional[T]]) -> 'OrderedSet[T]':
        result = self.difference(s)
        self.the_dict = result.the_dict
        return result

    def __xor__(self, s: AbstractSet[S]) -> 'OrderedSet[Union[T, S]]':
        return self.symmetric_difference(s)

    def __ixor__(self, s: AbstractSet[S]) -> 'OrderedSet[Union[T, S]]':
        result = self.symmetric_difference(s)
        self.the_dict = result.the_dict
        return result

    def __le__(self, s: AbstractSet[object]) -> bool:
        return self.issubset(s)

    def __lt__(self, s: AbstractSet[object]) -> bool:
        return self.issubset(s) and len(self) < len(s)

    def __ge__(self, s: AbstractSet[object]) -> bool:
        return set(iter(self)) >= set(iter(s))

    def __gt__(self, s: AbstractSet[object]) -> bool:
        return set(iter(self)) > set(iter(s))

这里有一些示例调用:

>>> from orderedset import OrderedSet
>>> s = OrderedSet([3, 1, 2])
>>> s
OrderedSet({3: None, 1: None, 2: None})
>>> list(s)
[3, 1, 2]
>>> set(s)
set()

有人知道这里发生了什么吗? set() 函数似乎是用冗长的 C 代码实现的,我对它的理解还不够深入,无法推断出任何东西。不过,似乎调用了 __iter__ 来转换为 list,而不是 set...

有什么想法吗?

非常感谢!

最佳答案

Python 3.9 或更高版本

您的类应该继承自 collections.abc.Set而不是 typing.Set (无论如何已被弃用)

from collections.abc import Set
...
class OrderedSet(Generic[T], Set[T]):
    ...

obj = OrderedSet()
obj.add(1)
obj.add(2)
obj.add(3)
print(set(obj)) # {1,2,3}

Python 3.8 或更低版本

在 3.9 之前,无法将泛型与 collections.abc.Set 一起使用。继承自 AbstractSet解决问题。

from typing import Generic, AbstractSet
...
class OrderedSet(Generic[T], AbstractSet[T]):
    ...

关于python - 转换为一组自定义集合类在 Python 中返回空集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70438357/

相关文章:

python - IMDB scrapy 获取元内容中的电影日期

java - 使用线程安全对 concurrentHashMap 进行排序

c++ - Dijkstra 算法 - 优先队列中的比较

Python:二维散点图网格(seaborn.PairGrid)

python - Pyinstaller: OSError: 找不到 Python 库

python - 我的时间戳字符串末尾有 "-05:00",这是什么意思,我该如何处理?

java - 在 Java 中将 Enum ArrayList 方法转换为 T[]

android - 使用 Collections.sort() 对对象进行排序。出现错误

javascript - 清除设置超时 Javascript

C89 开关盒成套使用