如何创建一个也是列表的类?

时间:2015-07-22 01:33:43

标签: python

我想用Python创建一个具有各种属性和方法的类,但是为了继承列表的功能,我可以将对象附加到对象本身,而不是任何属性。我希望能够说' graph[3]'而不是' graph.node_list[3]'。有没有办法做到这一点?

4 个答案:

答案 0 :(得分:10)

您真正需要做的就是提供__getitem__

In [1]: class Foo:
   ...:     def __init__(self, *args):
   ...:         self.args = args
   ...:     def __getitem__(self, i):
   ...:         return self.args[i]
   ...:     

In [2]: c = Foo(3,4,5)

In [3]: c[2]
Out[3]: 5

In [4]: c[3]
IndexError: tuple index out of range #traceback removed for brevity

In [5]: for i in c: print(i) #look, ma, I can even use a for-loop!
3
4
5

附录:您可能还想提供其他方法。 __len__绝对是其中之一。有一个相当长的魔术方法列表,我建议通过它们并选择有意义的方法。

答案 1 :(得分:5)

您可以继承list

class Foo(list):
    def __init__(self):
        pass

但是对内置类型进行子类化并不是一个好主意。

collections.abc.Sequence(或从3.5开始,typing.Sequence[T])是我的方式。

答案 2 :(得分:1)

您想添加一些特殊方法,例如列表中的__getitem__。看看:

https://docs.python.org/2/reference/datamodel.html#emulating-container-types

答案 3 :(得分:1)

由于Python使用duck typing,因此列表与任何其他对象之间的主要区别在于它公开的方法集。您可以使用dir()函数轻松查看对象的主要属性(方法和字段)。

>>> [a for a in dir([]) if callable(getattr([], a))]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__',
'__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__',
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__',
'__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']

显然这里有很多方法,你可能并不关心其中的大多数方法。但如果你的目标是真正复制列表的行为,你可能想要实现它们。大多数__...__方法都是在Python data model中定义的,如果你想查找它们的话。

从该页面开始:

  

可变序列应提供方法append()count()index()extend()insert()pop()remove()reverse()sort(),与Python标准列表对象一样。最后,序列类型应该通过定义方法__add__()__radd__()__iadd__()__mul__()__rmul__()来实现加法(意味着连接)和乘法(意味着重复)和__imul__()描述如下;他们不应该定义其他数字运算符。建议映射和序列都实现__contains__()方法以允许有效使用in运算符;对于映射,应该搜索映射的键;对于序列,它应该搜索值。进一步建议映射和序列都实现__iter__()方法,以允许有效迭代容器;对于映射,__iter__()应与keys()相同;对于序列,它应该遍历值。

__getitem__提供了您特别询问的功能,即索引查找。我建议至少实施__contains__()__iter__()(以及__len__())。