使 objects 可迭代?
Making objects iterable?
我尝试遍历列表列表中的每一行,将每一行的元素附加到新列表,然后在新列表中查找唯一元素。
我知道我可以使用 for 循环轻松完成此操作。我正在尝试不同的路线,因为我想了解更多关于 classes 和函数的信息。
这是列表列表的示例。第一行是 header:
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
我认为答案是尝试在我的 Dataset
class 中使用 def __iter__(self)
创建一个方法,但我无法让它工作。这是正确的轨道吗?如果不是,哪个更好?
你需要稍微改变一下
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()
根据the documentation for __iter__
:
This method should return a new iterator object that can iterate over all the objects in the container.
您可以尝试以下 class 定义:
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])
如您所述,您需要在 class Dataset
中实施 __iter__
。请注意,这实际上是引发错误的 set(...)
调用,因为它遍历您的 class 以枚举集合元素。
幸运的是,您的集合元素可能只是 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!
我尝试遍历列表列表中的每一行,将每一行的元素附加到新列表,然后在新列表中查找唯一元素。
我知道我可以使用 for 循环轻松完成此操作。我正在尝试不同的路线,因为我想了解更多关于 classes 和函数的信息。
这是列表列表的示例。第一行是 header:
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
我认为答案是尝试在我的 Dataset
class 中使用 def __iter__(self)
创建一个方法,但我无法让它工作。这是正确的轨道吗?如果不是,哪个更好?
你需要稍微改变一下
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()
根据the documentation for __iter__
:
This method should return a new iterator object that can iterate over all the objects in the container.
您可以尝试以下 class 定义:
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])
如您所述,您需要在 class Dataset
中实施 __iter__
。请注意,这实际上是引发错误的 set(...)
调用,因为它遍历您的 class 以枚举集合元素。
幸运的是,您的集合元素可能只是 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!