【问题标题】:Constrain type and attribute within a python container在 python 容器中约束类型和属性
【发布时间】:2018-02-21 12:40:44
【问题描述】:

我想构建一个容器来存储对象,并且我想限制容器只存储相同类型的对象(类型未先验定义)和不同的属性(例如,name 在下面的示例中,所以它可能是一个索引)。

以下是假设容器派生自list 对象的预期行为示例。

obj1 = Foo(name='Jon')
obj2 = Foo(name='Doe')
obj3 = Foo(name='Jon')
obj4 = Bar(name='Bob')

>>> MyContainer()
[]
>>> MyContainer([obj1, obj2])
[Foo(name='Jon'), Foo(name='Doe')]
>>> MyContainer([obj1, obj4])
TypeError: mixed types
>>> MyContainer([obj1, obj3])
ValueError: Same 'name' attribute

无论使用哪种方法填充容器,我都希望这种行为保持不变:__init____add____iadd__append、...

但是,如果可能的话,我希望一个空容器可以容纳任何类型,只要它都是一样的。

我想知道实施它的正确方法应该是什么,我正在寻找建议。到目前为止,我考虑过从list 派生它并重写方法,但我对此感到不舒服。我应该装饰它吗?我应该从头开始构建一个容器吗?是否已经有适合我目的的现有容器(一种 dict 或 pandas.Dataframe)?

【问题讨论】:

  • 你为什么需要这个?
  • 也许 ``collections.abc.MutableSequence` 可能是一个很好的起点......
  • @internet_user 我可以使用这样的容器来简化一段很长的代码,我使用list 以这种方式存储对象。我有很多容器,但都包含相同类型的对象,其属性只能是唯一的。

标签: python oop containers


【解决方案1】:

您可以从list 派生您的类来实现这一点,然后检查可以进入您的实例的所有点,无论进入的是Foo

class Foo: pass

class FooList(list):
  def __init__(self, elements):
    assert all(isinstance(element, Foo) for element in elements)
    super().__init__(elements)

  def append(self, element):
    assert isinstance(element, Foo)
    super().append(element)

  def __add__(self, other):
    return FooList(super().__add__(other))  # will do the checks implicitly

这只会在创建时检查。您现在可以继续并覆盖所有其他点(__iadd__()__setitem__()、...)并在那里引入检查。

我当前的实现只检查元素的类型。当然,您可以检查更多内容,例如检查您提到的相同名称。

不过,对于类型,我不确定这是一个好方法。不如使用 Python 的静态类型来代替?这不会在运行时引入太多开销。

【讨论】:

  • 当然,您可以提出ValueError(),而不是assert,这取决于您是否希望通过命令行开关优化检查(可以关闭断言)。跨度>
  • 感谢您的回答。不知何故,这就是我的想法,但我不确定这也应该是要走的路。我不知道静态类型,我会检查文档。
  • 静态打字工作得很好,但还很新,所以并不是每个深奥的方面都被完全涵盖。对于您的情况,它应该工作得很好。
猜你喜欢
  • 2014-12-18
  • 2021-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
相关资源
最近更新 更多