对于我的项目,讲师(定义为班级)的角色是向学生提供项目。项目本身也是一个类。我有一些全球词典,用于映射到对象的讲师和项目的唯一数字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_name
是class Lecturer
对象,等等。 Lecturer
和Project
类目前不相关。
但是,当我从文本文件中读取每一行时,对于该行,我希望将讲师提供的项目读入Lecturer
类;我已经在proj_id
课程中阅读Project
了。我想在Lecturer
中创建一个名为offered_proj
的对象,该对象应该是该讲师提供的项目集或列表。因此,无论何时,对于一行,我在同一lec_id
下的新项目中读取,offered_proj
将使用该项目进行更新。如果我想显示讲师提供的项目列表,我最好只想使用print lecturers[lec_id].offered_proj
。
我的Python并不出色,如果有人能告诉我一种方法,我会很感激。我不确定它作为一个集合或列表是否更好。
Update
在Alex Martelli和Oddthinking的建议之后,我回去做了一些更改并尝试打印结果。
以下是代码段:
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
的最后一个。
答案 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)
感谢您的帮助Alex和Oddthinking!我想我已经弄清楚发生了什么:
我修改了我添加到问题中的代码段。基本上,每当它读取该行时,我认为它正在重新创建讲师对象。因此,我输入了另一个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])
如果选择print
我lec_id
,我会获得完全更新的设置。高兴。