2010-07-07 38 views
7

首先,python是一种很棒的语言。这是我使用python的第一个项目,我已经取得了很大的进步。我该如何让这个python代码变得更难看

下面的代码没有办法做到这一点。写出类定义的最习惯的方式是什么?

class Course: 

    crn = course = title = tipe = cr_hours = seats = instructor = days = begin = end = location = exam = "" 

    def __init__(self, pyQueryRow): 
     self.crn = Course.get_column(pyQueryRow, 0) 
     self.course = Course.get_column(pyQueryRow, 1) 
     self.title = Course.get_column(pyQueryRow, 2) 
     self.tipe = Course.get_column(pyQueryRow, 3) 
     self.cr_hours = Course.get_column(pyQueryRow, 4) 
     self.seats = Course.get_column(pyQueryRow, 5) 
     self.instructor = Course.get_column(pyQueryRow, 6) 
     self.days = Course.get_column(pyQueryRow, 7) 
     self.begin = Course.get_column(pyQueryRow, 8) 
     self.end = Course.get_column(pyQueryRow, 9) 
     self.location = Course.get_column(pyQueryRow, 10) 
     self.exam = Course.get_column(pyQueryRow, 11) 

    def get_column(row, index): 
     return row.find('td').eq(index).text() 

谢谢!

回答

14
def__init__(self, pyQueryRow): 
    for i,attr in enumerate("crn course title tipe cr_hours seats instructor" 
          " days begin end location exam".split()): 
     setattr(self, attr, self.get_column(pyQueryRow, i)) 

这种方式避免了多次调用self.get_column

def__init__(self, pyQueryRow): 
    attrs = ("crn course title tipe cr_hours seats instructor" 
      " days begin end location exam".split()) 
    values = [td.text for td in pyQueryRow.find('td')] 
    for attr, value in zip(attrs, values): 
     setattr(self, attr, value) 
+0

这不危险吗?如果你拼错了该字符串中的成员会怎么样? – 2010-07-10 04:39:44

+1

@Assaf Lavie,就像在输入代码中输入属性名称一样。无论哪种方式,只有当您尝试访问不存在的属性时,Python才会投诉。通常你应该有单元测试来捕获这些类型的错误 – 2010-07-10 10:30:00

2

编辑:其实,最好的可能是:

self.crn, self.course, self.title, self.tipe, self.cr_hours, self.seats,\ 
self.instructor, self.days, self.begin, self.end, self.location, self.exam = \ 
[pq(td).text() for td in pyQueryRow.find('td')] 

,它假定您已经导入PyQuery为PQ。这避免了永远使用索引。


self.crn, self.course, self.title, self.tipe, self.cr_hours, self.seats,\ 
self.instructor, self.days, self.begin, self.end, self.location, self.exam = \ 
map(lambda index: get_column(pyQueryRow, index), xrange(0, 12)) 

,或者如果你想有一个列表理解:

self.crn, self.course, self.title, self.tipe, self.cr_hours, self.seats,\ 
self.instructor, self.days, self.begin, self.end, self.location, self.exam = \ 
[get_column(pyQueryRow, index) for index in xrange(0, 12)] 

我不知道这些是最地道的,但肯定有较少的样板。

另外,删除crn = course =。你正在分配给班级,而不是实例。

+0

是的,我想过一个类似的解决方案但不像你的那么优雅(列表理解而不是地图(当你认为地图是根据列表理解来定义时,这是愚蠢的))。 – Tyler 2010-07-07 06:43:33

+2

我喜欢lambda想法,但我不认为这实际上更具可读性,因为很难看到哪个索引被映射到哪个字段。想象一下,如果你不得不在某处添加一个 - 这很容易犯错误。 – EMP 2010-07-07 06:47:52

+0

@Evgeny,我明白你的意思了。但由于它基于抓取HTML页面,如果在中间添加了一个,其他人将会下移。你只需要把它放在正确的两个之间并递增最大值。 – 2010-07-07 06:52:18

2

我不确定是否有“更好”的方法。你有什么是肯定可读的。如果你想避免重复Course.get_column代码,你可以为它定义一个lambda表达式,例如Matthew Flaschen的答案。

class Course: 
    def __init__(self, pyQueryRow): 
     get_column = lambda index: pyQueryRow.find('td').eq(index).text() 

     self.crn = get_column(0) 
     self.course = get_column(1) 
     self.title = get_column(2) 
     self.tipe = get_column(3) 
     self.cr_hours = get_column(4) 
     self.seats = get_column(5) 
     self.instructor = get_column(6) 
     self.days = get_column(7) 
     self.begin = get_column(8) 
     self.end = get_column(9) 
     self.location = get_column(10) 
     self.exam = get_column(11) 

请注意,您不需要那么初始化所有的字段行“”事前 - 只设置它们__init__是罚款。事实上,正如马修所说,它设置了班级领域,而不是实例领域 - 我完全错过了这一点。

4

就个人而言,我会使用一个字典映射属性列编号:

class Course: 

    crn = course = title = tipe = cr_hours = seats = instructor = days = begin = end = location = exam = "" 

    def __init__(self, pyQueryRow): 
     course_row_mapping = { 
      'crn' : 0, 
      'course' : 1, 
      'title' : 2, 
      'tipe' : 3, # You probably mean "type"? 
      'cr_hours' : 4, 
      'seats' : 5, 
      'instructor' : 6, 
      'days' : 7, 
      'begin' : 8, 
      'end' : 9, 
      'location' : 10, 
      'exam' : 11, 
     } 

     for name, col in course_row_mapping.iteritems(): 
      setattr(self, name, Course.get_column(pyQueryRow, col)) 

    def get_column(row, index): 
     return row.find('td').eq(index).text() 
+0

迄今为止唯一可读的代码! – Pithikos 2015-03-10 17:34:33