2010-07-07 2 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

Разве это не рискованно? Что делать, если вы пропустили член в этой строке? –

+1

@Assaf Lavie, точно так же, как если бы вы ошибочно указали имя атрибута в своем коде. В любом случае Python не будет жаловаться, пока вы не попытаетесь получить доступ к атрибуту, который не существует. Обычно вы должны иметь модульные тесты, которые будут ловить те типы ошибок –

2

EDIT: На самом деле, лучше всего может быть:

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 в рд. Это позволяет избежать использования индексов вообще.


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

+2

Мне нравится идея лямбды, но я не думаю, что это на самом деле более читаемо, потому что трудно увидеть, какой индекс попадает в какое поле. Представьте себе, что вам нужно было добавить один посередине где-нибудь - было бы легко ошибиться. – EMP

+0

@ Эвгени, я понимаю, что вы имеете в виду. Но поскольку он основан на очистке страницы HTML, если ее добавить в середине, остальные будут сдвигаться вниз. Вам просто нужно поставить его между двумя правильными и увеличить максимум. –

2

Я не уверен, что существует «лучший» способ. То, что у вас есть, конечно, вполне читаемо. Если вы хотите избежать дублирования кода Course.get_column, вы можете определить лямбда для этого, как в ответе Мэтью Флашен, например.

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

Смежные вопросы