为什么`list(<dataframe>)`工作,即使DataFrame没有实现/继承__iter __()?</dataframe>

时间:2014-11-12 22:19:36

标签: python rpy2

我找不到__iter__()中定义的rpy2.robjects.DataFrame方法,也找不到任何基类*

然而,我可以使用this code将DataFrame转换为dict:

from rpy2.robjects import DataFrame
dataframe = DataFrame(...)

d = dict(zip(dataframe.names, map(list, list(dataframe))))

为什么上述代码中没有list(dataframe)触发TypeError: 'DataFrame' object is not iterable


*通过运行以下代码确定:

def test_attr(cls, attr):
  if attr in cls.__dict__:
    print cls.__name__
  else:
    for base in cls.__bases__:
      test_attr(base, attr)
Python 2.7.8 (default, Oct 18 2014, 05:53:47)
... 
>>> from rpy2.robjects import DataFrame
>>> test_attr(DataFrame, '__iter__')

2 个答案:

答案 0 :(得分:2)

我认为每个robject都实现了rinterface

您可以在

中看到__iter__方法

https://bitbucket.org/lgautier/rpy2/src/08ec0c15bd5ef8170ad8a49c2dc2b4a8dea36d64/rpy/rinterface/_rinterface.c?at=default#cl-2446

至少我认为......它很快就会很纠结

答案 1 :(得分:1)

list方法适用于iter方法。*并且,正如文档所说:

  

如果没有第二个参数,object必须是支持迭代协议(__iter__()方法)的集合对象,或者它必须支持序列协议(__getitem__()方法带整数从0开始的参数。


以下是没有定义__iter__的{​​{3}} **类的示例:

class Range10(object):
    def __getitem__(self, i):
        if i < 10: return i
        raise IndexError
r = Range10()
list(r)

输出为[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


如果你很好奇,这个&#34;序列协议&#34;如果有效for循环在早期Python中如何工作,但现代定义是为了向后兼容而创建的,当迭代器在Python 2.2中添加时。***它本可以在3.0中删除,但有很好的论据为什么这很有用,所以它保持不变。****


*实际上,至少在CPython中,它并不是它的实际工作方式,但它已被记录为工作,好像正在调用{{1} }。

**但请注意,它不是iterable,即使这是少数&#34;自动ABCs中的一个&#34;你不必继承/注册。文档明确没有说iter表示 iterable ;它说&#34;另见 iterable 的定义&#34;。

***例如,像Iterable这样的第三方库(今天的前身numeric)提供了在Python中numpy循环中起作用的集合类2.1,他们希望它们继续工作,即使现在根据迭代器实现了for循环。

****我不记得究竟是什么参数,但它必须通过思考序列协议来使某些类更易读/更容易理解。根据迭代协议手动再现相同的东西。您需要查看python-3000列表存档以获取详细信息。