python - 如何在类的实例上调用 list() 时让类返回列表

标签 python

当我拨打 list() 时,我试图返回一个列表在一个类上。什么是最好的方法来做到这一点。

class Test():
    def __init__(self):
        self.data = [1,2,3]
    def aslist(self):
        return self.data
a = Test()
list(a)
[1,2,3]

我要当list(a)被要求运行 aslist功能,理想情况下我想实现 asdict这在 dict() 时有效叫做

我希望能够通过 dict 做到这一点, int和所有其他类型的转换

最佳答案

与您可能习惯的许多其他语言(例如 C++)不同,Python 没有任何“类型转换”或“转换运算符”或类似的概念。
相反,Python 类型的构造函数通常被写入一些更通用的(鸭子类型)协议(protocol)。

首先要做的是查看您关心的任何构造函数的文档,看看它想要什么。开始于 Builtin Functions ,即使它们中的大多数会将您链接到 Builtin Types 中的条目.
其中许多将链接到 Data Model 中相关特殊方法的条目。章节。

例如, int 说:

… If x defines __int__(), int(x) returns x.__int__(). If x defines __trunc__(), it returns x.__trunc__()


然后您可以点击链接到 __int__ ,虽然在这种情况下没有太多额外的信息:

Called to implement the built-in functions complex(), int() and float(). Should return a value of the appropriate type.


所以,你想定义一个 __int__方法,它应该返回一个 int :
class MySpecialZero:
    def __int__(self):
        return 0 

序列和集合类型(如 listtuplesetfrozenset )有点复杂。他们都想要一个 iterable :

An object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict, file objects, and objects of any classes you define with an __iter__() method or with a __getitem__() method that implements Sequence semantics.


这在 iter 下解释得更好一些函数,这可能不是最明显的地方:

object must be a collection object which supports the iteration protocol (the __iter__() method), or it must support the sequence protocol (the __getitem__() method with integer arguments starting at 0) …


和下 __iter__ 在数据模型中:

This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container.

Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see Iterator Types.


因此,对于您的示例,您希望成为一个遍历 self.data 元素的对象。 ,这意味着您需要一个 __iter__在这些元素上返回迭代器的方法。最简单的方法是拨打 iterself.data ——或者,如果你想要的话 aslist其他原因的方法,请调用iter关于该方法返回的内容:
class Test():
    def __init__(self):
        self.data = [1,2,3]
    def aslist(self):
        return self.data
    def __iter__(self):
        return iter(self.aslist())
请注意,如 Edward Minnix explained , Iterator 和 Iterable 是分开的东西。当您调用 __iter__ 时,Iterable 可以生成迭代器。方法。所有的迭代器都是迭代器(它们自己产生),但许多迭代器不是迭代器(例如,像 list 这样的序列)。
dict (和 OrderedDict 等)也有点复杂。检查文档,你会看到它想要一个映射(即类似 dict 的东西)或一个可迭代的键值对(这些对本身就是可迭代的)。在这种情况下,除非您要实现完整映射,否则您可能需要回退:
class Dictable:
    def __init__(self):
        self.names, self.values = ['a', 'b', 'c'], [1, 2, 3]
    def __iter__(self):
        return zip(self.names, self.values)

几乎所有其他事情都很简单,例如 int ——但请注意 str , bytes , 和 bytearray是序列。

同时,如果您希望您的对象可以转换为 int或到 list或到 set ,您可能希望它在其他方面也表现得非常相似。如果是这样,请查看 collections.abc numbers ,它不提供不仅是抽象基类(用于检查某种类型是否符合某个协议(protocol))的助手,而且还提供混合(用于帮助您实现协议(protocol))。
例如,一个完整的 Sequence 预计提供与 tuple 相同的大部分方法——大约有 7 个 —— 但如果你使用 mixin,你只需要自己定义 2 个:
class MySeq(collections.abc.Sequence):
    def __init__(self, iterable):
        self.data = tuple(iterable)
    def __getitem__(self, idx):
        return self.data[idx]
    def __len__(self):
        return len(self.data)
现在您可以使用 MySeq几乎可以在任何地方使用 tuple ——包括构建一个list从它,当然。
对于某些类型,例如 MutableSequence ,快捷方式的帮助更大——您以 5 的价格获得 17 种方法。

如果您希望同一个对象既可列出又可听写……好吧,那么您就会遇到设计的限制。 list想要一个可迭代的。 dict想要一个可迭代的对,或一个映射——这是一种可迭代的。因此,您实际上只有两个,而不是无限的选择:
  • 迭代键并实现 __getitem__使用这些 key dict , 所以 list给出这些键的列表。
  • dict 迭代键值对, 所以 list给出这些键值对的列表。

  • 显然,如果你真的想表现得像 Mapping ,你只有一个选择,第一个。
    序列和映射协议(protocol)重叠的事实从一开始就是 Python 的一部分,这是您可以使用 [] 的固有事实。运算符,并且从那以后的每次重大更改都保留了下来,即使它使其他功能(如整个 ABC 模型)变得更加复杂。不知道有没有人给出过理由,但想必和扩展切片设计的原因差不多吧。换句话说,让字典和其他映射更容易使用和更易读是值得的,让它们变得更复杂,实现起来更不灵活。

    关于python - 如何在类的实例上调用 list() 时让类返回列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51219515/

    相关文章:

    python - Pytorch:如何生成长度在一定范围内的随机向量?

    python - 人机可读——文件中的结构化数据存储

    python - 为什么int.to_bytes中的括号不能省略?

    Python Pandas,将字符串列导出到 Excel 文件中

    python - 无法正确设置 dict 内的 dict 值

    python - 如何将 3d 张量传递给 tensorflow RNN embedding_rnn_seq2seq

    python - Ipython Notebook 不在数据框中打印 type()

    python - 打印浮点值时如何抑制科学计数法?

    python - Pandas 子字符串搜索过滤器

    python - 为什么 numpy.power 比 in-lining 慢 60 倍?