Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 29, 2016 10:57:55

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Питон 3.
Есть маленькая программа математических вычислений, результат выполнения которой должен быть представлен в форме отчёта. Под отчётом я подразумеваю:
- вывод данных в окне Pyton Shell
- копирование данных в буфер обмена
- сохранение данных в новый файл *.txt / *.doc / *.docx / *.rtf / *.pdf
Отчёт должен сохраняться в формат, указанный пользователем, а не во все сразу. Создавать кучу копий, конечно, не нужно.
Однако в ходе работы программы требуется диалог с пользователем с выводом справочной (дополнительной) информации - какой видно из примера ниже:

 x = 30
y = 50
print('x =',x)
print('y =',y)
print('''Вы хотите:
\a[1] Вычислить сумму
\a[2] Вычислить разность
\a[3] Вычислить умножение''')
n = int(input()); 
if n == 1:
    print('x+y=',x+y)
elif n == 2:
       print('x-y=',x-y)
elif n == 3:
       print('x*y=',x*y)
else:
    print('end')
Что видно сейчас в Pyton Shell:
x = 30
y = 50
Вы хотите:
  • Вычислить сумму
  • Вычислить разность
  • Вычислить умножение
2
x-y= -20
Из всего этого текста в отчёт должен попасть текст:
x = 30
y = 50
x-y= -20
В примере я показал лишь одну выходную формулу, а их будут десятки и n-ое количество диалогов и справок.
Мой вопрос в том, как правильно выстроить архитектуру программы, чтобы было возможным получать данные отчёты?

Отредактировано Kyrym (Дек. 30, 2016 07:46:15)

Офлайн

#2 Дек. 29, 2016 21:29:20

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Kyrym
Мой вопрос в том, как правильно выстроить архитектуру программы
:) очевидно единственно правильного варианта нет.

В вашем решении любого программиста покоробит огромное количество ручных действий и куча никому не нужных промежуточных файлов.

Классический вариант решения протоколирование результата модулем logging и последующее необязательное форматирование в любой нужный формат.

Делайте сразу pdf документ. Красивый отчет не получится из данных которые вы просто валите в кучу на выход. Надо сделать хотябы элементарное форматирование Например:

 from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table
 
doc = SimpleDocTemplate("simple_table.pdf", pagesize=letter)
elements = []
data= [ ["x  ", "=", "30"],
["y  ", "=", "50"],
["x-y", "=", "-20" ] ]
t=Table(data)
elements.append(t)
# write the document to disk
doc.build(elements)

Фрагмент сбора данных может вот так выглядеть:

 data =[]
while(1):
  if n == 1:
    print('x+y=',x+y)
    data.append( ("x+y","=", x+y) )



Отредактировано doza_and (Дек. 29, 2016 21:43:19)

Офлайн

#3 Дек. 30, 2016 04:28:10

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10010
Репутация: +  857  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Kyrym
Мой вопрос в том, как правильно выстроить архитектуру программы, чтобы было возможным получать данные отчёты?
 #!/usr/bin/env python3
 
def dialog(text):
    x = 2
    y = 3
    while True:
        s = input(text)
        if s == '1':
            print('x + y =', x + y)
        elif s == '2':
            print('x - y =', x - y)
        elif s == '3':
            print('x * y =', x * y)
        elif s == 'q':
            print('end')
            break
 
def main():
    msg = ('Введите число (q - для выхода).\n'
           'Вы хотите:\n'
           '[1] Вычислить сумму\n'
           '[2] Вычислить разность\n'
           '[3] Вычислить умножение\n')
    dialog(msg)
 
if __name__ == '__main__':
    main()    

Вывод
[guest@localhost userdialog]$ ./userdialog.py 
Введите число (q - для выхода).
Вы хотите:
[1] Вычислить сумму
[2] Вычислить разность
[3] Вычислить умножение
1
x + y = 5
Введите число (q - для выхода).
Вы хотите:
[1] Вычислить сумму
[2] Вычислить разность
[3] Вычислить умножение
2
x - y = -1
Введите число (q - для выхода).
Вы хотите:
[1] Вычислить сумму
[2] Вычислить разность
[3] Вычислить умножение
3
x * y = 6
Введите число (q - для выхода).
Вы хотите:
[1] Вычислить сумму
[2] Вычислить разность
[3] Вычислить умножение
q
end
[guest@localhost userdialog]$



Отредактировано py.user.next (Дек. 30, 2016 04:30:30)

Офлайн

#4 Дек. 30, 2016 08:08:46

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Я несколько дополнил первый пост, чтобы меня лучше поняли.

py.user.next, Вы ведь просто сделали цикл для программы, но задача совсем иная.

doza_and
В вашем решении любого программиста покоробит огромное количество ручных действий
Если честно, я совсем не понял о каких ручных действиях идёт речь?
doza_and
и куча никому не нужных промежуточных файлов
Я уточнил в первом посте, что куча копий в разных форматах не нужна. Я просто показал область форматов, которые мне интересны. И ждал, что если с сохранением в какие-либо форматы будут проблемы, то об этом что-нибудь напишут.

В общем, Вы предлагаете под каждым нужным print'ом добавлять .append. А разве нет более удобного решения, чем переписывать print? Что-то типа “предыдущую строку добавить в список”? Может это делается функцией?

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

Офлайн

#5 Дек. 30, 2016 08:35:04

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10010
Репутация: +  857  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Kyrym
py.user.next, Вы ведь просто сделали цикл для программы, но задача совсем иная.
Дальше подключай функции к выбранным пунктам, а внутри функций уже сохраняй что надо и куда надо. Я просто сделал диалог, потому что в исходном сообщении никакой не диалог, а просто фуфел одноразовый. Заодно показал тебе, что не надо их в числа преобразовывать, потому что тогда ты лишаешь себя букв и даже фраз, на которые тоже можно реагировать (что часто требуется в подобных программах).



Отредактировано py.user.next (Дек. 30, 2016 08:36:05)

Офлайн

#6 Дек. 30, 2016 08:54:36

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой


Kyrym
Если честно, я совсем не понял о каких ручных действиях идёт речь?
Вот об этих:
Kyrym
- копирование данных в буфер обмена
После этого я посчитал что вы из ворда будете pdf лепить и rtf ручками.
Kyrym
И ждал, что если с сохранением в какие-либо форматы будут проблемы, то об этом что-нибудь напишут.
Я написал что doc/rtf нежелателен. Как сделать pdf написал.
Kyrym
Вы предлагаете под каждым нужным print'ом добавлять .append. А разве нет более удобного решения. Может это делается функцией?
Вы занялись программированием, но пока похоже представляете что на каждое ваше желание есть функция но просто не знаете как ее найти, как объяснить поисковому движку что вы хотите.

А мне кажется что если вам нужна такая функция то вы должны так объяснять что вы хотите:
Открываете текстовый редактор и пишете
 def my_funny_print(*argv,**kvarg):
    print(*argv,**kvarg)
    do_some_more()

Вот и искать ничего не надо, вы уже и так получили то что хотели.

Kyrym
Насколько я понимаю, мой вопрос не является уникальным.
Нет вы ошибаетесь. Ваш вопрос уникален. Никто так не делает, потому что при записи данных в файлы для создания отчета обычного принта недостаточно, нужна разметка текста которая определит форматирование, а при логгировании данных она загромоздит вывод и его будет неудобно смотреть на консоли. Многолетние усилия программистов всего мира по изобретению единого способа форматирования вывода любой программы привели только к изобретению терминала и широкому применению символов табуляции и перевода строки.

А когда кто-то хочет получить одинаковые данные и в файле и в консоли то пишут так:

 my_python_prog.py | tee out.txt

запись в stdout любой программы можно перенаправить в программу tee она пишет данные в свой выходной поток и одновременно в файл. Питон как видите тут не нужен, надо просто знать свойства своей операционной системы.





Офлайн

#7 Янв. 11, 2017 13:15:19

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Я только изучаю функции и классы, получается пока плохо, поэтому запустить эту штуку у меня не получилось:

 def my_funny_print(*argv,**kvarg):
    print(*argv,**kvarg)
    do_some_more()
Я напипсал следующий код:
 # Питон 3
def my_funny_print(*argv,**kvarg):
    print(*argv,**kvarg)
    # do_some_more()
    
x = 30
y = 50
print('x+y=',x+y)
q = 'x+y='+str(x+y)
print(my_funny_print())
Что такое “do_some_more()” я не понял, поэтому исключил из кода.
Вообще с помощью аппенда я получил, что хотел:
 # Питон 3
data = []
        
print('-'*30,'''
Ход програмы''')    
x = 30
y = 50
# Выражение 1
i = 'x+y='+str(x+y)
print(i)
data.append(i)
# Лишний для отчёта текст
print('Лишний для отчёта текст')
# Выражение 2
i = 'x-y='+str(x-y)
print(i)
data.append(i)
# Блок отчётов
print('-'*30,'''
Текст отчёта списка data''')
for i in data:
    print(i)
В результате видим:
——————————
Ход програмы
x+y=80
Лишний для отчёта текст
x-y=-20
——————————
Текст отчёта списка data
x+y=80
x-y=-20
Единственное, мне не нравится, что приходится писать повторяющийся код:
 print(i)
data.append(i)
Я так понимаю, что моя задача должна решаться через классы (как пишет Лутц, если у вас есть желание копировать код, значит, ищите другое решение), но тут труба… Вот что я наколякал (естественно не работает, не пойму даже, как заставить класс выполняться).
 # Питон 3
data = []
class Ot:
    def __init__(self, x):
        self.x = x
    def my_funny_print(*argv,**kvarg):
        print(*argv,**kvarg)
class Ot2:
    def __init__(self, x):
        self.x = x
        self = data.append(x)
        return()
        
print('-'*30,'''
Ход програмы''')    
x = 30
y = 50
# Выражение 1
i = 'x+y='+str(x+y)
print(i)
x = Ot2('i')
# Лишний для отчёта текст
print('Лишний для отчёта текст')
# Выражение 2
i = 'x-y='+str(x-y)
print(i)
x = Ot2('i')
# Блок отчётов
print('-'*30,'''
Текст отчёта списка data''')
for i in data:
    print(i)

Отредактировано Kyrym (Янв. 11, 2017 13:16:09)

Офлайн

#8 Янв. 11, 2017 20:09:27

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Kyrym
Я так понимаю, что моя задача должна решаться через классы
Нет не обязательно. Вообще похоже вам пока рано классами пользоваться.
Kyrym
Что такое “do_some_more()” я не понял, поэтому исключил из кода.
А вам название функции ничего не сказало? По русски функция называлась бы сделать_чтото_еще()
Kyrym
Единственное, мне не нравится, что приходится писать повторяющийся код:
Вот внутри функции и можно было выполнить append чтобы не писать его каждый раз снаружи
 def my_funny_print(*argv,**kvarg):
    print(*argv,**kvarg)
    data.append(argv)
my_funny_print('x-y', x-y)
my_funny_print('x+y', x+y)

А равенство (“x-y=”) это уже стиль оформления и его обычно выносят в код записи и форматирования данных



Офлайн

#9 Янв. 12, 2017 13:18:07

Kyrym
Зарегистрирован: 2016-12-28
Сообщения: 225
Репутация: +  3  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

doza_and
Вообще похоже вам пока рано классами пользоваться.
Я так не думаю.
“do_some_more()” - я понял, что это не объявленная функция. А Вашу мысль можно было выразить иначе… Но не о том речь.

Написал я свою функцию. Работает исправно:
 # Питон 3
# -*- coding: utf-8 -*-
data = []
def viv(i):
    i = ''.join(map(str, i))
    data.append(i)
    return(print(i))
        
print('-'*30,'''
Ход програмы''')    
x = 30
y = 50
# Выражение 1
i = 'γ = x+y = '+str(x+y)
print(i)
data.append(i)
# Выражение 3
i = ['ξ = x/y = ',x/y]
viv(i)
# Блок отчётов
print('-'*30,'''
Текст отчёта списка data''')
for i in data:
    print(i)

Офлайн

#10 Янв. 12, 2017 19:35:34

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Вывод решения за вычетом диалога с программой

Kyrym
А Вашу мысль можно было выразить иначе…
:) Безусловно. Неплохо если вы приведете пример как на ваш взгляд правильно.
Kyrym
Но не о том речь.
Kyrym
Работает исправно:

Я поясню свою мысль по поводу того что классы вам пока не нужны.

 # Питон 3
# -*- coding: utf-8 -*-
data = []
# -------- функции нужны чтобы убрать повторяющийся код - у вас функция используется один раз.  значит не надо было ее писать
def viv(i):
    i = ''.join(map(str, i))
    data.append(i)
    return(print(i)) #-------- строка не имеет смысла print ничего не возвращает
        
print('-'*30,'''
Ход програмы''')    #------- я бы сделал print("-"*30+"\nХод програ[b]М[/b]мы") но это дело вкуса
x = 30
y = 50
# Выражение 1
i = 'γ = x+y = '+str(x+y) #------- зачем i=, зачем str(x+y) можно просто написать print('γ = x+y = ', x+y)
print(i)
data.append(i) #--------- тут по идее должен быть viv
# Выражение 3
i = ['ξ = x/y = ',x/y]
viv(i)
# Блок отчётов
print('-'*30,'''
Текст отчёта списка data''')
for i in data: #----------- тут вообще непонятно зачем опять на консоль писать надо по идее в файл
    print(i)

После учета правок код выглядит так

 x,y = 30,50
def viv(z):
    a = "{0} -> {1}".format(z,eval(z))
    print(a)
    return a
b="\n".join(map(viv,["x+y","x/y"]))
print("""------------------
Ход програмы
%s
Текст отчёта списка data
------------------""" % b)

Вам не стоит усложнять программу классами, она и так у вас слишком сложная и непонятная.
Надеюсь я теперь понятнее выразился?



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version