Найти - Пользователи
Полная версия: Вывод решения за вычетом диалога с программой
Начало » Python для новичков » Вывод решения за вычетом диалога с программой
1 2
Kyrym
Питон 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-ое количество диалогов и справок.
Мой вопрос в том, как правильно выстроить архитектуру программы, чтобы было возможным получать данные отчёты?
doza_and
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) )
py.user.next
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]$
Kyrym
Я несколько дополнил первый пост, чтобы меня лучше поняли.

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

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

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

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

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 она пишет данные в свой выходной поток и одновременно в файл. Питон как видите тут не нужен, надо просто знать свойства своей операционной системы.



Kyrym
Я только изучаю функции и классы, получается пока плохо, поэтому запустить эту штуку у меня не получилось:
 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)
doza_and
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=”) это уже стиль оформления и его обычно выносят в код записи и форматирования данных
Kyrym
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)
doza_and
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)

Вам не стоит усложнять программу классами, она и так у вас слишком сложная и непонятная.
Надеюсь я теперь понятнее выразился?
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