Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Общие вопросы > Использование процедур


Автор: diam 12.2.2007, 15:03
Итак, есть рутинный код.
Код

try:
    loader = loader.car.get_loader('User1')
    for i in loader.get_info():
        # рутина... И то, что выше, тоже рутина

    loader = loader.model.get_loader('User1')
    for i in loader.get_info():
        # рутина...

    loader = loader.car.get_loader('User2')
    for i in loader.get_info():
        # рутина...
except (loader.car.ExistsError, loader.model.ExistsError), e:
    # действия с объектом loader, в том числе сохранение некоторой информации
    log.write(loader.get_page())


Собственно говоря, блоки с рутиной повторяются периодически, и как-то неправильно писать по несколько раз один и тот же код. Сразу же напрашивается использование процедур (ООП здесь использовать, на мой взгляд, нерационально, так как рутинные действия используются только в одном месте - при загрузке информации с сайта).
Что нужно блокам для использования в моём случае? Только имя пользователя, под которым заходить на сайт. И всё. А получить нужно объект загрузчика, причём тот, где произошла ошибка. Например, загружали машины, нужен объект loader.car.get_loader(), загружали модели, нужен loader.model.get_loader().

В голову пришёл только такой вариант:
Код

def load_car(user):
    global loader
    loader = loader.car.get_loader(user)
    # рутина

def load_model(user):
    global loader
    loader = loader.model.get_loader(user)
    # рутина

try:
    load_car('User1')
    load_model('User1')
    load_car('User2')
    # и т.д.
except (loader.car.ExistsError, loader.model.ExistsError), e:
    # действия с объектом loader, в том числе сохранение некоторой информации
    log.write(loader.get_page())

Но этот вариант мне совершенно ненравится из-за использования global.

Какие ещё могут быть варианты?

Автор: Daevaorn 12.2.2007, 18:29
Не очень понимаю зачем тут global. мне кажется либо нужно возвращать loader из функции, либо объявить его вне функции.

Автор: diam 12.2.2007, 19:34
loader из функции возвращать не получится, поскольку может быть сгенерировано исключение. А вот записать так действительно можно:
Код

def load_car():
    # рутина

def load_model():
    # рутина

try:
    loader = loader.car.get_loader('User1')
    load_car()
    loader = loader.model.get_loader('User1')
    load_model()
    loader = loader.car.get_loader('User2')
    load_car()
    # и т.д.
except (loader.car.ExistsError, loader.model.ExistsError), e:
    # действия с объектом loader, в том числе сохранение некоторой информации
    log.write(loader.get_page())


Ещё варианты?

Автор: Daevaorn 12.2.2007, 19:51
я не знаю что такое loader, поэтому не могу понять почему у тебя что-то вызвает проблему

Автор: setq 12.2.2007, 22:38
Вложи в try... for по ('User1', 'User2'...) .

Автор: sir_Jack 12.2.2007, 23:10
тоже не до конца осознал суть кода, но если тебе надо знать в котором из вызовов load_car, load_model произошло исключение, то почему бы не внести это в переменную?

Код

def load_func(mode,user):
    #something
    pass

# try, except, ... - как нравится
load_func('car','user1')
load_func('model','user1')
load_func('car','user2')
load_func('model','user2')


Не то? 

Автор: diam 13.2.2007, 12:51
Цитата(Daevaorn @  12.2.2007,  22:51 Найти цитируемый пост)
я не знаю что такое loader, поэтому не могу понять почему у тебя что-то вызвает проблему 

Код сильно утрирован, что было проще описать проблему. Но всё же немного опишу loader.
loader - объект, который используется для загрузки информации с www-сайта. Один из методов, который мне от него нужен при генерации исключения - get_page(). Возвращает страницу, которую разбирал и на которой накололся (изменилась структура представления данных, скорее всего). Позже я эти страницы разбираю и корректирую алгоритм получения данных. Собственно, поэтому он мне и нужен при генерации исключения.

Цитата(setq @  13.2.2007,  01:38 Найти цитируемый пост)
Вложи в try... for по ('User1', 'User2'...) . 

На самом деле, процедур таких много, и так их перечислять не имеет смысла, вопрос в другом: как написать эти процедуры и впоследствии их вызывать, что бы связь с переменной loader не терялась.
Обратите внимание, что переменная loader в разных участках кода хранит у меня разные объекты.
Код

# один объект
loader = loader.car.get_loader('User1')
# другой объект
loader = loader.model.get_loader('User1')
# третий объект
loader = loader.car.get_loader('User2')


Цитата(sir_Jack @  13.2.2007,  02:10 Найти цитируемый пост)
тоже не до конца осознал суть кода, но если тебе надо знать в котором из вызовов load_car, load_model произошло исключение, то почему бы не внести это в переменную?

Потому что при генерации исключения я потеряю эту самую переменную loader, из-за которой бьюсь.

Добавлено @ 13:01 
Давайте попробуем по другому.
Итак, есть несколько кусков кода.
Кусок 1:
Код

x += 1
print x

Кусок 2:
Код

x -= 2
print x

Кусок 3:
Код

x *= 3
print x

И так далее.

В коде программы мне нужно периодически вызывать эти куски, по разному меняя их местами, при этом необходимо, что бы переменная x никуда не исчезала. Т.е., выглядеть это должно примерно так:
Код

x = 10
кусок_кода1
x = 3
кусок_кода2
кусок_кода3
x = 4
for i in xrange(10):
    кусок_кода1
    кусок_кода3
    кусок_кода2
# и т.д.

Автор: diam 15.2.2007, 13:11
Другого решения не нашёл.
Код

# описываем (часто) повторяющийся код
def piece_of_code1():
    global x
    x += 1
    print x

def piece_of_code2():
    global x
    x -= 2
    print x

def piece_of_code3():
    global x
    x *= 3
    print x

# используем описанный выше код
x = 10
piece_of_code1()
x = 3
piece_of_code2()
piece_of_code3()
x = 4
for i in xrange(10):
    piece_of_code1()
    piece_of_code2()
    piece_of_code3()
# и т.д.


У кого ещё будут мысли?

Автор: albertn 15.2.2007, 15:08
А почему бы не использовать классы, передавать их в функцию, а функция уже будет менять внутренние поля.

Добавлено @ 15:09 
кстати и функции можно определить внутри этого класса

Автор: diam 15.2.2007, 15:33
Цитата(albertn @  15.2.2007,  18:08 Найти цитируемый пост)
А почему бы не использовать классы, передавать их в функцию, а функция уже будет менять внутренние поля.

Код в "кусках кода" жутко утрирован. И переменная "x" в моём настоящем коде есть объект loader:
Цитата(diam @  13.2.2007,  15:51 Найти цитируемый пост)
loader - объект, который используется для загрузки информации с www-сайта. Один из методов, который мне от него нужен при генерации исключения - get_page(). Возвращает страницу, которую разбирал и на которой накололся (изменилась структура представления данных, скорее всего). Позже я эти страницы разбираю и корректирую алгоритм получения данных. Собственно, поэтому он мне и нужен при генерации исключения.

Поэтому мне так важна эта переменная. А куски кода запихал в функции piece_of_code по причине частой повторяемости кода.

Но может я неверно воспринимаю, что ты хочешь сказать?
Цитата(albertn @  15.2.2007,  18:08 Найти цитируемый пост)
А почему бы не использовать классы, передавать их в функцию, а функция уже будет менять внутренние поля.


albertn, покажи пример, пожалуйста.

Автор: albertn 15.2.2007, 15:57
Цитата(diam @  15.2.2007,  15:33 Найти цитируемый пост)
albertn, покажи пример, пожалуйста. 

Переделал исходный код:
Код

class class_x:
    def __init__(self,loader):
        self.loader = loader
    
    def load_car(self,user):
        self.loader = self.loader.car.get_loader(user)
        # рутина

    def load_car(self,user):
        self.loader = self.loader.car.get_loader(user)
        # рутина

x = class_x(loader)

try:
    x.load_car('User1')
    x.load_model('User1')
    x.load_car('User2')
    # и т.д.
except (x.loader.car.ExistsError, x.loader.model.ExistsError), e:
    # действия с объектом loader, в том числе сохранение некоторой информации
    log.write(x.loader.get_page())


Хотя мне не нравится запись вида loader = loader.model.get_loader('User1'), и мне кажется, что красивее менять поля самого объекта а не заменять объект на другой.

Автор: diam 15.2.2007, 19:24
albertn, идея понятна, спасибо.

Замечания.
1. В таком виде оно не работает. Проверил на Python2.5. И было бы странно, если бы заработало. Потому как loader.car и loader.model - это модули, что такое x.loader.car и x.loader.model?
2. Как я уже говорил, всевозможные loader'ы - это разные объекты. Каждый из них отвечает за определённую страницу на сайте. Более того, одна и та же страница под разными пользователями позволяет делать разные вещи (скачивать счета в формате pdf под одним, просматривать список входящих машин под другим; ну это так, для примера). Соответственно, у этих загрузчиков и информация разная, и методы её выуживания, и методы её представления. Поэтому "менять поля самого объекта" не получится.

Если довести до рабочего вида, будет примерно следующее:
Код

class X:
    # текущий загрузчик
    loader = None

    def load_car(self, user):
        self.loader = loader.car.get_loader(user)
        # рутина

    def load_model(self, user):
        self.loader = loader.model.get_loader(user)
        # рутина

x = X()
try:
    x.load_car('User1')
    x.load_car('User2')
    # etc
except (loader.car.ExistsError, loader.model.ExistsError), e:
    # действия с объектом loader, в том числе сохранение некоторой информации
    log.write(x.loader.get_page())


За идею +.

Автор: albertn 16.2.2007, 09:34
Цитата(diam @  15.2.2007,  19:24 Найти цитируемый пост)
В таком виде оно не работает

Код не проверял, т.к. у меня небыло самого loader

Цитата(diam @  15.2.2007,  19:24 Найти цитируемый пост)
что такое x.loader.car и x.loader.model?

Это тот-же самый loader, только лежащий внутри объекта x

Цитата(diam @  15.2.2007,  19:24 Найти цитируемый пост)
За идею +. 

Спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)