Найти - Пользователи
Полная версия: Как лучше проработать условие ?
Начало » Python для новичков » Как лучше проработать условие ?
1
r4khic
Есть код:
 count = 0
sql = '''INSERT INTO items (res_id, log_id, link, title, content, n_date, nd_date, s_date, not_date) VALUES'''
    for resource_link in resources_links:
        try:
            exist_link = parser.check_exist_link(resource_link)
            if exist_link is not True:
                goose_date = parser.get_goose_date(resource_link)
                time_now = parser.get_time_now()
                if goose_date is not None:
                    #if goose_date <= time_now:
                    date_parsed = parser.get_converted_date(goose_date)
                    nd_date = parser.get_nd_date(date_parsed)
                    not_date = parser.get_not_date(date_parsed)
                    n_date = parser.get_n_date()
                    s_date = parser.get_s_date()
                    log_id = parser.get_log_id()
                    item_title = parser.get_item_title(resource_link)
                    item_content = parser.get_item_content(resource_link)
                    if item_title != '' and item_content != '':
                        count+=1
                        sql +=  ''',('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')''' % (
                         res_id,
                         log_id,
                         str(resource_link),
                         str(item_title),
                         str(item_content),
                         str(n_date),
                         nd_date,
                         s_date,
                         not_date)
                        sql = sql.replace('VALUES,', 'VALUES')
                        if count == 20:
                            huge_insert = parser.huge_insert_db(sql)
                            sql = ''
                            count = 0
                            print('Запись  новостей произведена!')
                    else:
                        print('Нету заголовка или котента.')
                else:
                    print('Гусь не нашел дату.')
            else:
                print('Новость уже есть в базе.')
        except Exception as e:
            print(f'Ошибка: {str(e)}')
В этом коде создана инт переменная и увеличивается на единицу после каждой итерации.После стоит условие как только количество итераций будет 20 - я делаю вставку и обнуляю переменную.Но вот загвоздка а что если допустим на ресурсе появятся 25 новостей.А в БД добавятся только 20, остальные 5 не добавятся.А мне надо чтобы и эти 5 новостей добавились.
Можно как-то реализовать если обнаружится чтобы к примеру 25 новостей,и сперва добавятся 20 а потом и остальные 5 новостей ?
Как это можно продумать ?

P.S:Второй день ломаю над этим голову.
FishHook
r4khic

Есть такое правило хорошего кода, не помню как это правильно называется, назовем его “правило раннего выхода”. Суть в том, чтобы как можно выше к началу функции проверять условия и выходить из функции не умножая вложенность операторов.

   
def foo(i):
    if i > 0:
        do_something()
        do_something()
        do_something()
        do_something()
        do_something()
        if do_something_else():
            do_something()
            do_something()
            do_something()
            do_something()
        else:
            print()
    else:
        print()
в общем случае это плохо, следующий код читается и поддерживается лучше
   
def foo(i):
    if i <= 0:
        print ("improper i")
        return 
    do_something()
    do_something()
    do_something()
    do_something()
    do_something()
    if not do_something_else():
        print ("improper do_something_else")
        return
    do_something()
    do_something()
    do_something()
    do_something()
код получается менее вложенным (более плоским), и следовательно его легче читать и проще в нем разбираться. Кроме того, это делает более логичными условия. Вместо
 if item_title != '' and item_content != '':
будет
 if item_title == '' or item_content == '':
мы заменили “отрицательную” логику на “положительную”. Как правило это более очевидно. Попробуйте переписать с учетом моего замечания, и возможно, сами найдете ошибку. Кроме тго, я не понимаю, почему вы в одном месте закономерно используете удобный современный синтаксис подстановки строк, а в другом малоочевидный и архаичный.
Rafik
r4khic
если допустим на ресурсе появятся 25 новостей.А в БД добавятся только 20, остальные 5 не добавятся
Дык, никто не мешает проверить состояние счётчика после завершения цикла. Если он больше 0, то пишем в БД. После завершения цикла в твоём sql будут, как раз, те самые 5, которые не попали в двадцатку.
Rodegast
Зачем тебе нужно это условие? Сразу новости в базу пиши.
r4khic
FishHook
r4khicЕсть такое правило хорошего кода, не помню как это правильно называется, назовем его “правило раннего выхода”. Суть в том, чтобы как можно выше к началу функции проверять условия и выходить из функции не умножая вложенность операторов.
Благодарю за ответ и пояснение этой темы.Для меня как новичку это очень важно.В будущем буду стараться делать код более плоским.

FishHook
Вместо
if item_title != ‘' and item_content != ’':
Мне кажется это условие более корректней.Потому что здесь условие такое:“Если item_title не равен пустой строке и item_content тоже не равен пустой строке” выполняется блок условий.
А ваше условие
FishHook
if item_title == ‘' or item_content == ’':
Такое: “Если item_title равен пустой строке или item_content пустой строке”.Это условие не работает в моем коде.В любом случае благодарю за то уделили мне внимание.
FishHook
r4khic
Мне кажется это условие более корректней.Потому что здесь условие такое:“Если item_title не равен пустой строке и item_content тоже не равен пустой строке” выполняется блок условий.
А ваше условие
FishHook
if item_title == ‘' or item_content == ’':
Такое: “Если item_title равен пустой строке или item_content пустой строке”.Это условие не работает в моем коде.В любом случае благодарю за то уделили мне внимание.

Вам неправильно кажется. Не надо “выполнять блок условий”, надо проверить отграничения и прервать выполнение или продолжить.

Вместо вот этого
 if item_title != '' and item_content != '':
      count+=1
      sql +=  ''',('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')'''
else:
      print('Нету заголовка или котента.')

сделайте вот так
 if item_title == '' or item_content == '':
      print('Нету заголовка или котента.')
      continue
count+=1
sql +=  ''',('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')'''
вы проверяете условие и прекращаете выполнение ветки кода при его соблюдении. Дальше вам уже не надо держать в голове это условие, так как вы на первом уровне вложенности. Ваш алгоритм не ветвится, поэтому его сложность для вас не возрастает, у вас меньше возможности запутаться и совершить ошибку.
Вместо проверки условия “надо ли выполнять блок кода”, проверяйте условие “есть ли ошибка”.


r4khic
FishHook
сложность для вас не возрастает, у вас меньше возможности запутаться и совершить ошибку.
Вместо проверки условия “надо ли выполнять блок кода”, проверяйте условие “есть ли ошибка”.
Аа теперь я понял ! Благодарю
r4khic
Правильно ли я сделал ?
FishHook
сделайте вот так
 # -*- coding: utf-8 -*-
from boilerpipe_parser_component import boilerpipe_parser
from pprint import pprint
# < Создаем обьект класса.
parser = boilerpipe_parser()
# < Вызываем метод класса.
resources = parser.get_resources()
# < Шаблон insert запроса.
sql = '''INSERT INTO items (res_id, log_id, link, title, content, n_date, nd_date, s_date, not_date) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)'''
items_data = []
for resource in resources:
    # < Айди ресурса.
    res_id = resource[0]
    # < Ссылка ресурса.
    resource_url = resource[3]
    # < Ссылки на новости.
    resource_main_url = resource[4]
    link_rules = resource[5]
    # < Разбиваем по ',' правило выдергивание контента в массив.
    link_rule = link_rules.split(',')
    # < Переопределение переменной для того чтобы в методе 'get_resource_links' соединять ссылки.
    resource_domain = resource_url
    # < Вызов методов класса.
    resource_page = parser.get_html(resource_main_url)
    resources_links = parser.get_resource_links(resource_page, link_rule, resource_domain)
    print('id resource: ' + str(res_id))
    print('Количество ссылок: '+str(len(resources_links)))
    for resource_link in resources_links:
        try:
            exist_link = parser.check_exist_link(resource_link)
            if exist_link is True:
                print('Новость уже есть в базе.')
                continue
            goose_date = parser.get_goose_date(resource_link)
            time_now = parser.get_time_now()
            if goose_date is None:
                print('Гусь не нашел дату.')
                continue
            if goose_date >= time_now:
                print('Найдена дата будущего.')
                continue
            date_parsed = parser.get_converted_date(goose_date)
            nd_date = parser.get_nd_date(date_parsed)
            not_date = parser.get_not_date(date_parsed)
            n_date = parser.get_n_date()
            s_date = parser.get_s_date()
            log_id = parser.get_log_id()
            item_title = parser.get_item_title(resource_link)
            item_content = parser.get_item_content(resource_link)
            if item_title == '' and item_content == '':
                print('Нету заголовка или котента.')
                continue
            items_data.append((res_id,
                               log_id,
                               str(resource_link),
                               str(item_title),
                               str(item_content),
                               str(n_date),
                               nd_date,
                               s_date,
                               not_date))
            if len(items_data) == 100:
                huge_insert = parser.huge_insert_db(sql, items_data)
                sql = ''
                items_data = []
                print('inset completed')
        except Exception as e:
            print(f'Ошибка: {str(e)}')
FishHook
r4khic

Так уже лучше. Двигаемся дальше. Первое маленькое замечание
 if exist_link is True:
Зачем это? Не надо проверять на True и False. Выражение exist_link is True вернет True или False. Зачем нужно это выражение, если ваша переменная exist_link и так содержит True или False? масло масляное.

Теперь по коду и стилю. У вас происходит перманентная борьба с собственным кодом. Смотрите что вам приходится писать, чтобы самому же понять результат работы собственной же функции
 for resource in resources:
    # < Айди ресурса.
    res_id = resource[0]
    # < Ссылка ресурса.
    resource_url = resource[3]
    # < Ссылки на новости.
    resource_main_url = resource[4]
    link_rules = resource[5]
То есть ваша структура resource, которую вы сами придумали и возврашаете из метода get_resources() требует дальнейшей дополнительной расшифровки. И это справедливо, потому что мне, читающему ваш код вовсе не очевидно, под какими индексами в кортеже resource скрываются какие именно данные. Ну так не используйте кортеж, если его строение не вытекает логично из природы самих данных. Сделайте resource объектом класса Resource, и ваш код сразу станет приятнее, и не понадобится никаких глупых комментариев.
Далее, вам надо декомпозировать вашу программу. Разбейте задачу на небольшие логически инкапсулируемые подзадачи и оформите их в виде функций. У вас слишком много кода подряд, чтобы с ним легко было работать. Как-то вот так как мне видится

 def parse():
     source_getter = SourceGetter()
     parser = Parser()
     data_saver = DataSaver()
     for site in source_getter.get_sources():
           try:
                data = parser.parse(site)
                data_saver.save(data)          
          except ParserError:
                print("bla bla")
          except SaverError:
                print("bla bla") 

Вот как-то так должна выглядеть ваша программа - маленькая, простая и для каждой строчки очевидно, что она делает.

Это не все замечания, но было бы здорово, если бы вы переделали хотябы с учетом вышесказанного.



r4khic
FishHook
Зачем это? Не надо проверять на True и False. Выражение exist_link is True вернет True или False. Зачем нужно это выражение, если ваша переменная exist_link и так содержит True или False? масло масляное.
Понял,принял и изменил !
FishHook
r4khicТак уже лучше. Двигаемся дальше. Первое маленькое замечание
Не могу.Так как я принимаю эти данные кортежом из БД
FishHook
Вам надо декомпозировать вашу программу
Я понимаю,но я не могу так сделать так как все мои основные методы и они в другом модуле.
Благодарю вас за ваше внимание и понимание !
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB