使对象可迭代?

时间:2017-08-15 19:20:50

标签: python class iterable

我试图遍历列表列表中的每一行,将每行中的元素追加到新列表中,然后在新列表中找到唯一元素。

我知道我可以使用for循环轻松完成此操作。我正尝试不同的路线,因为我想了解更多有关课程和功能的知识。

这是列表列表的一个示例。第一行是标题:

legislators = [
 ['last_name', 'first_name', 'birthday', 'gender', 'type', 'state', 'party'],
 ['Bassett', 'Richard', '1745-04-02', 'M', 'sen', 'DE', 'Anti-Administration'],
 ['Bland', 'Theodorick', '1742-03-21', '', 'rep', 'VA', ''],
 ['Burke', 'Aedanus', '1743-06-16', '', 'rep', 'SC', ''],
 ['Carroll', 'Daniel', '1730-07-22', 'M', 'rep', 'MD', ''],
 ['Clymer', 'George', '1739-03-16', 'M', 'rep', 'PA', ''],
 ['Contee', 'Benjamin', '', 'M', 'rep', 'MD', ''],...]

这是我的代码:

import csv
f = open("legislators.csv")
csvreader = csv.reader(f)
legislators = list(csvreader)

class Dataset:
    def __init__(self, data):
        self.header = data[0] #Isolate header from CSV file
        self.data = data[1:] #Subset CSV data to remove header

legislators_dataset = Dataset(legislators)

def the_set_maker(dataset):
    gender = []
    for each in dataset:
        gender.append(each[3])
    return set(gender)

t=the_set_maker(legislators_dataset)
print(t)

我收到以下错误:

TypeErrorTraceback (most recent call last)
<ipython-input-1-d65cb459931b> in <module>()
     20     return set(gender)
     21
---> 22 t=the_set_maker(legislators_dataset)
     23 print(t)

<ipython-input-1-d65cb459931b> in the_set_maker(dataset)
     16 def the_set_maker(dataset):
     17     gender = []
---> 18     for each in dataset:
     19         gender.append(each[3])
     20     return set(gender)

TypeError: 'Dataset' object is not iterable

我认为答案是尝试在我的def __iter__(self)课程中使用Dataset创建一个方法,但我还没有能够让它发挥作用。这是正确的轨道吗?如果没有,哪个更好?

3 个答案:

答案 0 :(得分:4)

根据the documentation for __iter__

  

此方法应返回一个新的迭代器对象,该对象可以迭代容器中的所有对象。

您可以尝试以下类定义:

class Dataset:
    def __init__(self, data):
        self.header = data[0] #Isolate header from CSV file
        self.data = data[1:] #Subset CSV data to remove header

    def __iter__(self):
        return iter(self.data)

如果您尝试使用新选项,请考虑使用Pandas:

import pandas as pd
df = pd.read_csv('legislators.csv')
t=df['gender']

或者,如果您真的想自己阅读CSV,

df = pd.DataFrame(legislators[1:], columns=legislators[0])

答案 1 :(得分:2)

如您所述,您需要在__iter__中实施class Dataset。请注意,这实际上是set(...)调用引发错误的调用,因为它会遍历您的类以枚举集合元素。

幸运的是,您的设置元素可能只有Dataset.data,这样可以轻松编写Dataset.__iter__

class Dataset(object):
    ...

    def __iter__(self):
        return iter(self)
但是,我会指出,你的the_set_maker函数似乎有点过于专业而无法成为顶级函数。它也有点微不足道,因为它实际上是set([el[3] for el in container])。我也会把它放在Dataset中。

class Dataset(object):
    ...

    def to_set(self):
        return set([el[3] for el in self.data])
        # Note that this throws away your header!

答案 2 :(得分:-2)

你需要改变一点

class Dataset:
    i = 0

    def __init__(self, data):
        self.header = data[0] #Isolate header from CSV file
        self.data = data[1:] #Subset CSV data to remove header

    def __iter__(self):
        return self
    def __next__(self):
        return self.next()

    def next(self):
        if self.i < len(self.data):
            self.i += 1
            return self.data[self.i-1]
        else:
            raise StopIteration()