【问题标题】:Why does `list(<DataFrame>)` work even though DataFrame doesn't implement/inherit __iter__()?为什么即使 DataFrame 没有实现/继承 __iter__(),`list(<DataFrame>)` 仍然有效?
【发布时间】:2015-01-09 22:36:19
【问题描述】:

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

不过,我可以使用 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(默认,2014 年 10 月 18 日,05:53:47) ... >>> 从 rpy2.robjects 导入 DataFrame >>> test_attr(DataFrame, '__iter__')

【问题讨论】:

  • rpy2.robjects.Vector 中有__getslice__。另外,__getitem__.
  • 你能在交互式提示符下输入rpy2.robjects.Dataframe.__iter__,看看它是打印出函数还是内置函数,还是引发AttributeError?这将使答案更容易找到。
  • 从您的编辑中,您还没有尝试打印出Dataframe.__iter__吗?虽然这不会在所有情况下识别它定义的类,但它至少是测试它是否存在的一种快速可靠的方法......

标签: python rpy2


【解决方案1】:

我认为每个 robject 都实现了 rinterface

你可以在

中看到__iter__方法

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

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

【讨论】:

  • 我尝试查看代码,并认为不值得尝试解开……很好的侦探工作。
  • 这很好,但在这里并没有太大帮助..它甚至没有显示 rinterface ...即使它显然是一个基类类型
  • @lgautier: 好吧,我在放弃之前只到了Vector,所以这可能至少可以帮助我减少部分搜索……但幸运的是,Joran 在不到无论如何,我还是放弃了。 :)
【解决方案2】:

list 方法根据 iter 方法工作。* 而且,正如文档所说:

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


这是一个 iterable** 类示例,但未定义 __iter__

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]


如果你很好奇,这个“序列协议”如果在早期的 Python 中有效地工作 for 循环,但是当在 Python 2.2 中添加迭代器时,现代定义是为了向后兼容而创建的。*** 它可能有在 3.0 中被删除,但有充分的理由说明它为什么有用,所以它保留了。****


* 实际上,至少在 CPython 中,它实际上不是这样工作的,但它被记录为工作就好像它正在调用 iter

** 但请注意,它不是an Iterable,尽管这是您不必继承/注册的少数“自动 ABC”之一。文档明确没有说 Iterable 表示 iterable;它说“另见 iterable 的定义”。

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

**** 我不记得参数到底是什么,但它一定与某些类通过考虑序列协议而不是手动来更易读/更容易理解有关根据迭代协议再现相同的事物。您必须在 python-3000 列表档案中寻找详细信息。

【讨论】:

  • 天哪,这太酷了……我从来不知道你能做到这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2020-09-09
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多