Питоновский скрипт калькулятора

Тема в разделе "WASM.LANGS", создана пользователем GRAFik, 24 мар 2023.

  1. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    352
    Как-то давно, попался мне на просторах интернета, приаттаченный ниже Питоновский скрипт калькулятора. Заработал он лишь частично. Т.е. ГУИ - вроде, работает (и-то кривовато, нет раскраски, которая есть в скрипте), а вот с математикой - вообще беда. Работает одно сложение (+), причем тоже с небольшими странностями: кнопку равно (=) нужно нажимать два раза. И вот тоже исключительно "для образовательных целей и спортивного интереса" захотелось исправить скрипт и понять ход мыслей автора сего бреда. В принципе если нужно, я могу реализовать подобный скрипт калькулятора еще как минимум несколькими вариантами непохожими друг на друга. Но тут дело принципа - захотелось разобраться именно с этим вариантом, чтобы проверить знание Питона на практике. Но знаний не хватило, а спортивный интерес остался. :) Может кто поможет подправить скрипт - чисто из образовательных целей и спортивного интереса?
    Код (Python):
    1. from tkinter import *
    2.  
    3. class Window:
    4.     def __init__(self, width, height, title="FirstTK", resizable=(False, True), icon=None):
    5.         self.root = Tk()  # корневая переменная которая хранит с себе экземпляр класса Tk
    6.         self.root.title(title)
    7.         self.root.geometry(f"{width}x{height}+200+200")
    8.         self.root.resizable(resizable[0], resizable[1])
    9.         if icon:
    10.             self.root.iconbitmap(icon)
    11.         self.label_out = Label(self.root, text='0', font=("Verdana", 10, "bold"))
    12.     def run(self):
    13.         self.draw_widgets()
    14.         self.root.mainloop()
    15.     def draw_widgets(self):
    16.         self.draw_menu()
    17.         self.label_out.place(x=30, y=10)
    18.         Button(self.root, width=1, height=1, text='1', font=("Verdana", 10, "bold"),
    19.                command=lambda: self.test_button('1')).place(x=30, y=30)
    20.         Button(self.root, width=1, height=1, text='2', font=("Verdana", 10, "bold"),
    21.                command=lambda: self.test_button('2')).place(x=60, y=30)
    22.         Button(self.root, width=1, height=1, text='3', font=("Verdana", 10, "bold"),
    23.                command=lambda: self.test_button('3')).place(x=90, y=30)
    24.         Button(self.root, width=1, height=1, text='4', font=("Verdana", 10, "bold"),
    25.                command=lambda: self.test_button('4')).place(x=30, y=60)
    26.         Button(self.root, width=1, height=1, text='5', font=("Verdana", 10, "bold"),
    27.                command=lambda: self.test_button('5')).place(x=60, y=60)
    28.         Button(self.root, width=1, height=1, text='6', font=("Verdana", 10, "bold"),
    29.                command=lambda: self.test_button('6')).place(x=90, y=60)
    30.         Button(self.root, width=1, height=1, text='7', font=("Verdana", 10, "bold"),
    31.                command=lambda: self.test_button('7')).place(x=30, y=90)
    32.         Button(self.root, width=1, height=1, text='8', font=("Verdana", 10, "bold"),
    33.                command=lambda: self.test_button('8')).place(x=60, y=90)
    34.         Button(self.root, width=1, height=1, text='9', font=("Verdana", 10, "bold"),
    35.                command=lambda: self.test_button('9')).place(x=90, y=90)
    36.         Button(self.root, width=1, height=1, text='0', font=("Verdana", 10, "bold"),
    37.                command=lambda: self.test_button('0')).place(x=30, y=120)
    38.         Button(self.root, width=1, height=1, text='+', font=("Verdana", 10, "bold"),
    39.                command=lambda: self.test_button('+')).place(x=60, y=120)
    40.         Button(self.root, width=1, height=1, text='-', font=("Verdana", 10, "bold"),
    41.                command=lambda: self.test_button('-')).place(x=90, y=120)
    42.         Button(self.root, width=1, height=1, text='*', font=("Verdana", 10, "bold"),
    43.                command=lambda: self.test_button('*')).place(x=30, y=150)
    44.         Button(self.root, width=1, height=1, text='/', font=("Verdana", 10, "bold"),
    45.                command=lambda: self.test_button('/')).place(x=60, y=150)
    46.         Button(self.root, width=1, height=1, text='=', font=("Verdana", 10, "bold"),
    47.                command=self.solve).place(x=90, y=150)
    48.     def draw_menu(self):
    49.         menu_bar = Menu(self.root)
    50.         file_menu = Menu(menu_bar, tearoff=0)
    51.         color_menu = Menu(file_menu, tearoff=0)
    52.         color_menu.add_command(label='Зеленый', command=lambda: self.change_color('green'))
    53.         color_menu.add_command(label='Красный', command=lambda: self.change_color('red'))
    54.         color_menu.add_command(label='Сброс', command=lambda: self.change_color('white'))
    55.         menu_bar.add_cascade(label='Настройки', menu=file_menu)
    56.         file_menu.add_cascade(label='Цвет фона', menu=color_menu)
    57.         self.root.configure(menu=menu_bar)
    58.     def change_color(self, color):
    59.         self.root.configure(bg=color)
    60.     def test_button(self, val):
    61.         if self.label_out.cget("text") in ('0', 'ERROR', 'ZERO DIVISION'):
    62.             self.label_out.config(text=val)
    63.         else:
    64.             if (val == '+' and self.label_out.cget("text")[-1] == '+') or (
    65.                     val == '-' and self.label_out.cget("text")[-2] == '-'):
    66.                 return
    67.             else:
    68.                 old_label_val = self.label_out.cget("text")
    69.                 new_val = old_label_val + val
    70.                 self.label_out.config(text=new_val)
    71.     def solve(self):
    72.         try:
    73.             str_ = self.label_out.cget("text")
    74.             token_list = []
    75.             token = []
    76.             for i in range(len(str_)):
    77.                 if str_[i].isdigit():
    78.                     token += [str_[i]]
    79.                 else:
    80.                     token_list += [token]
    81.                     token = []
    82.                     token += [str_[i]]
    83.                     token_list += [token]
    84.                     token = []
    85.             if len(token):
    86.                 token_list += [token]
    87.             result = list(filter(lambda a: a, map(lambda x: ''.join(x), token_list)))
    88.             def to_number(x):
    89.                 return int(x) if x.isdigit() else x
    90.             result2 = list(map(to_number, result))
    91.             print(result2)
    92.             for i in range(len(result2)):
    93.                 if not isinstance(result2[i], int) and result2[i + 1] == '-':
    94.                     result2[i + 2] = ~result2[i + 2] + 1
    95.                     result2[i + 1] = None
    96.             final_result1 = list(filter(lambda x: x is not None, result2))
    97.             print(final_result1)
    98.             # здесь вставить обработку первого минуса для выражений типа -765+64
    99.             test_null = False
    100.             def insert_change(x):
    101.                 nonlocal test_null
    102.                 if final_result1[i] == 'x':
    103.                     if not final_result1[i + 1]:
    104.                         test_null = True
    105.                         return
    106.                     product = final_result1[i - 1] * final_result1[i + 1] if x == '*' else final_result1[i - 1] / \
    107.                                                                                            final_result1[
    108.                                                                                                i + 1]
    109.                     final_result1[i - 1] = None
    110.                     final_result1[i] = None
    111.                     final_result1[i + 1] = None
    112.                     final_result1.insert(i + 1, product)
    113.                     print( final_result1)
    114.             print(test_null)
    115.             for i in range(len(final_result1)):
    116.                 insert_change('*')
    117.                 insert_change('/')
    118.             final_result2 = list(filter(lambda x: x is not None, final_result1))
    119.             print(final_result2)
    120.             if test_null:
    121.                 self.label_out.config(text='ZERO DIVISION')
    122.             else:
    123.                 solution = final_result2[0]
    124.                 for i in range(len(final_result2) - 1):
    125.                     if final_result2[i] == '+':
    126.                         solution += final_result2[i + 1]
    127.                     if final_result2[i] == '-':
    128.                         solution -= final_result2[i + 1]
    129.                 self.label_out.config(text=str(solution))
    130.         except IndexError:
    131.             self.label_out.config(text='ERROR')
    132.         except TypeError:
    133.             self.label_out.config(text='ERROR')
    134. if __name__ == "__main__":
    135.     window = Window(150, 200)
    136.     window.run()
    Форумный редактор "исправил" скрипт сделав его, вообще, нерабочим, поэтому дополню пост зип-архивом. :)
     

    Вложения:

  2. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    594
    Вот я и не люблю из-за этого питухон. Это скрипт просто так не запустишь, если питухон не установлен. А калькулятор можно и на делфи или даже на ассемблере написать, и по трудозатратам это будет легче.
    Питухон такой ПИТУХОН!!!
     
  3. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    проблема с гуЁвиной не из-за питона - просто в лине есть два мейнстрима для гуЁвины (гном/жтк и кеды/кьюти), а в скрипте ТС вообще зло-2,72..ий ткинтер привязан.. теоретически он должен бесшовно пахать, но это лишь теоретически :) лучший вариант - на кьюти переписать, а если уж совсем хочется избавить себя от страданий - можно сделать консольную версию :)