如何在Python中的类中创建列表或设置对象?

时间:2010-02-19 03:59:09

标签: python class dictionary

对于我的项目,讲师(定义为班级)的角色是向学生提供项目。项目本身也是一个类。我有一些全球词典,用于映射到对象的讲师和项目的唯一数字ID。

因此对于“讲师”字典(目前):

lecturer[id] = Lecturer(lec_name, lec_id, max_students)

我目前正在读取一个从数据库生成的以空格分隔的文本文件。我没有直接访问数据库所以我没有太多说文件的格式。这是一个虚构的片段,显示了文本文件的结构。请原谅这种俗气。

0001 001 "Miyamoto, S." "Even Newer Super Mario Bros"
0002 001 "Miyamoto, S." "Legend of Zelda: Skies of Hyrule"
0003 002 "Molyneux, P." "Project Milo"
0004 002 "Molyneux, P." "Fable III"
0005 003 "Blow, J." "Ponytail"

每一行的结构基本上是proj_id, lec_id, lec_name, proj_name

现在,我正在将相关数据读入相关对象。因此,proj_id存储在class Project中,而lec_nameclass Lecturer对象,等等。 LecturerProject类目前不相关。

但是,当我从文本文件中读取每一行时,对于该行,我希望将讲师提供的项目读入Lecturer类;我已经在proj_id课程中阅读Project了。我想在Lecturer中创建一个名为offered_proj的对象,该对象应该是该讲师提供的项目集或列表。因此,无论何时,对于一行,我在同一lec_id下的新项目中读取,offered_proj将使用该项目进行更新。如果我想显示讲师提供的项目列表,我最好只想使用print lecturers[lec_id].offered_proj

我的Python并不出色,如果有人能告诉我一种方法,我会很感激。我不确定它作为一个集合或列表是否更好。

Update

Alex MartelliOddthinking的建议之后,我回去做了一些更改并尝试打印结果。

以下是代码段:

for line in csv_file:
    proj_id = int(line[0])
    lec_id = int(line[1])
    lec_name = line[2]
    proj_name = line[3]
    projects[proj_id] = Project(proj_id, proj_name)
    lecturers[lec_id] = Lecturer(lec_id, lec_name)
    if lec_id in lecturers.keys():
        lecturers[lec_id].offered_proj.add(proj_id)
    print lec_id, lecturers[lec_id].offered_proj

print lecturers[lec_id].offered_proj行打印以下输出:

001 set([0001])
001 set([0002])
002 set([0003])
002 set([0004])
003 set([0005])

它基本上感觉就像集合被覆盖或者某些东西。因此,如果我尝试为特定讲师print lec_id, lecturers[001].offered_proj打印,那么我得到的就是已读过的proj_id的最后一个。

3 个答案:

答案 0 :(得分:4)

set更好,因为您不关心订单而且没有重复。

您可以使用csv模块轻松解析文件(delimiter' ')。

一旦你拥有lec_name,你必须检查那位讲师是否已经知道;为此目的,保留一个从lec_name到讲师对象的字典(这只是对同一个讲师对象的另一个引用,你也可以从lecturer字典中引用)。在找到不在该字典中的lec_name时,你知道它是以前没见过的讲师,所以在这种情况下,制作一个新的讲师对象(并坚持两种方式),提供一套空的课程。最后,只需.add当前讲师offered_proj的课程。这真是一个非常顺利的流程。

您是否尝试过实施此流程?如果是这样,你有什么问题?你能告诉我们相关的代码 - 最多应该是十几行吗?

编辑:既然OP已经发布了代码,我可以发现错误 - 就在这里:

lecturers[lec_id] = Lecturer(lec_id, lec_name)
if lec_id in lecturers.keys():
    lecturers[lec_id].offered_proj.add(proj_id)

这是无条件地创建一个新的讲师对象(践踏lecturers dict中的旧对象,如果有的话),所以当然前一组被抛弃了。这是您需要的代码:首先检查,并仅在需要时创建! (还有,小错误,不要检查in....keys(),这非常低效 - 只需检查dict中的存在)。如下:

if lec_id in lecturers:
    thelec = lecturers[lec_id]
else:
    thelec = lecturers[lec_id] = Lecturer(lec_id, lec_name)
thelec.offered_proj.add(proj_id)

你可以用几种不同的方式表达这一点,但我希望这很清楚。为了完整起见,我通常会用它来表达它的方式(避免两次查询字典)如下:

thelec = lecturers.get(lec_id)
if thelec is None:
    thelec = lecturers[lec_id] = Lecturer(lec_id, lec_name)
thelec.offered_proj.add(proj_id)

答案 1 :(得分:1)

当您想要保证每个项目只有一个实例时,设置非常有用。在计算集合中是否存在项目时,它们也比列表更快。

列表在添加项目时速度更快,并且还有订购。

这听起来像你想要一套。你听起来已经很近了。

在Lecturer。 init 中,添加一行:

self.offered_proj = set()

这将是一个空集。

当您在项目中阅读时,您只需添加到该集:

lecturer.offered_proj.add(project)

你可以按照你的建议进行打印(虽然你可能会喜欢它。)

答案 2 :(得分:0)

感谢您的帮助AlexOddthinking!我想我已经弄清楚发生了什么:

我修改了我添加到问题中的代码段。基本上,每当它读取该行时,我认为它正在重新创建讲师对象。因此,我输入了另一个if语句,用于检查字典中是否已存在lec_id。如果是,则跳过对象创建,然后简单地将项目添加到offered_proj集。

我所做的改变是:

if not lec_id in lecturers.keys():
    projects[proj_id] = Project(proj_id, proj_name)
lecturers[lec_id] = Lecturer(lec_id, lec_name)
lecturers[lec_id].offered_proj.add(proj_id)

由于我的朋友萨米尔,我最近才发现if not背后的概念。

现在我得到以下输出:

001 set([0001])
001 set([0001, 0002])
002 set([0003])
002 set([0003, 0004])
003 set([0005])

如果选择printlec_id,我会获得完全更新的设置。高兴。